UserControl不向窗口发送依赖属性更改

时间:2013-11-24 20:20:18

标签: c# wpf xaml dependency-properties

我有一个自定义树视图用户控件,我想在主窗口中公开一对可绑定属性。

在我的树形视图中,我执行了此操作后的用户控制代码。

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,但我认为这与我的问题无关。我认为更多的是缺乏对依赖属性如何工作的理解。

有没有人知道为什么这不起作用?或者为什么在更改后面的代码被识别,但它们不会被推回到我的主窗口?

修改 我注意到当我通过绑定设置属性时,更新将在用户控件中触发,但仍然无法弄清楚为什么更改不会出现另一种方式。

2 个答案:

答案 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流,并且您将能够绑定到超级树视图。