2010-09-10 70 views
3

嵌套视图模型设置为主窗口的DataContext:绑定到在代码嵌套的对象属性后面

var mainWindow = new MainWindow(); 
mainWindow.Show(); 
mainWindow.DataContext = new 
{ 
    MyProperty = new 
    { 
     MySubProperty = "Hello" 
    } 
} 

这是很容易结合到MySubProperty在XAML:

<Button Content="{Binding MyProperty.MySubProperty}"/> 

我该怎么办这在代码背后的绑定?

// MyButton.xaml.cs 
public partial class MyButton : Button 
{ 
    public MyButton() 
    { 
     InitializeComponent(); 
     // todo: add binding here 
    } 

    // I want this method called if this datacontext is set. 
    // and called if MySubProperty changes and INotifyPropertyChange is implemented in the Datacontext. 
    public void MySubPropertyChanged(string newValue) 
    { 
     // ... 
    } 
} 

我无法访问MyButton.xaml.cs中的MainWindow,因此我无法将其用作源文件。

按钮只是一个例子,但它将是一个开始。 在我原来的场景中,我没有任何有用的依赖项属性。如果一个dp对于这样一个绑定是必要的,一个例子会非常有帮助,包括创建一个dp。

回答

1

这个怎么样? (只是一个肮脏的例子和未经考验的,原则上应当工作)

// MyButton.xaml.cs 
public partial class MyButton : Button 
{ 
    public MyButton() 
    { 
     InitializeComponent(); 
     this.DataContextChanged += DataContext_Changed; 
    } 

    private void DataContext_Changed(Object sender,DependencyPropertyChangedEventArgs e) 
    { 
     INotifyPropertyChanged notify = e.NewValue as INotifyPropertyChanged; 
     if(null != notify) 
     { 
      notify.PropertyChanged += DataContext_PropertyChanged; 
     } 
    } 

    private void DataContext_PropertyChanged(Object sender,PropertyChangedEventArgs e) 
    { 
     if(e.PropertyName == "MySubProperty") 
      MySubPropertyChanged((sender as YourClass).MySubProperty); 
    } 

    public void MySubPropertyChanged(string newValue) 
    { 
     // ... 
    } 
} 

编辑:

绑定在代码隐藏的东西,你可以使用:

Binding binding = new Binding(); 
// directly to myproperty 
binding.Source = MyProperty; 
binding.Path = new PropertyPath("MySubProperty"); 
// or window 
binding.Source = mainWindow; // instance 
binding.Path = new PropertyPath("MyProperty.MySubProperty"); 

// then wire it up with (button is your MyButton instance) 
button.SetBinding(MyButton.MyStorageProperty, binding); 
//or 
BindingOperations.SetBinding(button, MyButton.MyStorageProperty, binding); 
+0

非常感谢您花时间回答。我不知道/我忘了DataContextChanged被调用,如果父母的DataContext被改变。但是,如果数据更加嵌套,编码工作会增加,所以这似乎不是最好的方法。所以我不会将你的答案设定为接受的答案。 – 2010-09-11 12:03:48

+0

@您的编辑:谢谢。但是我没有MyButton类中的MyProperty实例和MainWindow实例。 – 2010-09-11 15:29:37

+1

如果你是绑定的,你可以在DataContext – MrDosu 2010-09-11 16:30:39

0

在我原来的问题,我没有依赖属性。所以我创建了一个。

public partial class MyButton : Button 
{ 
    //... 

    public string MyStorage 
    { 
     get { return (string)GetValue(MyStorageProperty); } 
     set { SetValue(MyStorageProperty, value); } 
    } 

    public static DependecyProperty MyStorageProperty = 
     DependencyProperty.Register("MyStorage", typeof(string), typeof(MyButton), 
      new UIPropertyMetadata(OnMyStorageChanged)); 
    public static void OnMyStorageChanged(DependecyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     var myButton = d as MyButton; 
     if (myButton == null) 
      return; 
     myButton.OnMyStorageChanged(d,e); 
    } 

    public void OnMyStorageChanged(object sender, DependencyPropertyChangedEventArgs e) 
    { 
     // ... 
    } 
} 

现在我可以在XAML中设置

<local:MyButton MyStorage="{Binding MyProperty.MySubProperty}"/> 

绑定这解决了我的问题。但是我仍然很好奇如何在没有XAML的情况下执行此绑定。