我有一个自定义树视图用户控件,我想在主窗口中公开一对可绑定属性。
在我的树形视图中,我执行了此操作后的用户控制代码。
TreeViewControl.xaml.cs
public static readonly DependencyProperty SelectedFolderProperty =
DependencyProperty.Register("SelectedFolder", typeof (Folder), typeof (TreeViewControl),
new FrameworkPropertyMetadata(OnFolderChanged));
public Folder SelectedFolder
{
get { return (Folder)GetValue(SelectedFolderProperty); }
set { SetValue(SelectedFolderProperty, value); }
}
private static void OnFolderChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
//just wanted to test if we get here, which we do everytime
MessageBox.Show("WeChanged");
}
private void TreeView_OnSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
var folderViewModel = e.NewValue as FolderViewModel;
if (folderViewModel != null)
{
//this is where we change the dependency property value
SelectedFolder = folderViewModel.Folder;
}
}
我真的不关心通过这个属性设置值,只是阅读它们。我知道应该在这里使用只读属性,但此时我只是想让任何工作正常。
我将它绑定在我的主窗口中,就像这样
MainWindow.xaml
<controls:TreeViewControl SelectedFolder={Binding MySelectedFolder, Mode=TwoWay} />
然后在我的主视图模型中
MainWindowViewModel.cs
private Folder _mySelectedFolder;
public Folder MySelectedFolder
{
get {return _mySelectedFolder;}
set {this.RaiseAndSetIfChanged(ref _mySelectedFolder, value); }
}
//constructor
public MainWindowViewModel()
{
//just listen for changes
this.ObservableForProperty(x => x.MySelectedFolder).Subscribe(x => {
//this will never get hit, and MySelectedFolder is always null
MessageBox.Show("The selection was changed");
});
}
如果重要的话我只是将主窗口绑定到像这样的视图模型
MainWindow.xaml.cs
public class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new MainWindowViewModel();
}
}
所以问题是主窗口永远不知道任何SelectedFolder的变化,我希望如此。目前我不知道接下来要尝试使用这些更改。我不知道出了什么问题。
如果不明显,我在这里使用ReactiveUI,但我认为这与我的问题无关。我认为更多的是缺乏对依赖属性如何工作的理解。
有没有人知道为什么这不起作用?或者为什么在更改后面的代码被识别,但它们不会被推回到我的主窗口?
修改 我注意到当我通过绑定设置属性时,更新将在用户控件中触发,但仍然无法弄清楚为什么更改不会出现另一种方式。
答案 0 :(得分:1)
我仍然不确定造成这种情况的确切问题。我认为它与在我的主窗口中设置datacontext,然后将其设置为控件内的其他东西(不同的视图模型)之类的东西有关。
不知何故,这会让绑定系统混淆不清?
无论如何,为了实现这一点,我将Source部分添加到绑定中,因此我的主窗口xaml看起来像这样
<Window.Resources>
<local:MainWindowViewModel Key="MainWindowViewModel" />
</Window.Resources>
<!-- Later on -->
<controls:TreeViewControl SelectedFolder={Binding MySelectedFolder, Source={StaticResource MainWindowViewModel}}" />
如果有人能向我解释为什么我必须明确告诉绑定来源,我很乐意将你的答案标记为已接受的答案。
答案 1 :(得分:1)
您的问题与DataContext有关。 要解决此问题,您需要执行以下操作:
在TreeViewControl.xaml中: 在UserControl声明中应用x:Name属性,如下所示:
<UserControl x:Class="TreeViewControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Name="thisUserControl">
在绑定中引用ElementName以绑定到此属性:
<TreeView SelectedItem={Binding ElementName=thisUserControl, Path=SelectedFolder} />
这样您就不会从ViewModel中弄乱DataContext流,并且您将能够绑定到超级树视图。