绑定到ViewModel属性时,WPF用户控件依赖项属性不起作用

时间:2014-08-18 20:57:35

标签: c# wpf xaml mvvm user-controls

我有两个用户控件:LocationTreeView和LocationPicker。 LocationTreeView将Locations组织为树结构。由于所涉及的位置数量,一次只加载树的一部分(扩展项目时一次一个级别)。

LocationPicker只是一个带有按钮的文本块,可以打开一个带有LocationTreeView的模态窗口。

当我将LocationPicker的“SelectedLocation”属性绑定到我的Viewmodel时,它可以正常工作。当我将LocationTreeView绑定到viewmodel时,绑定似乎根本没有任何效果。当我将LocationTreeView绑定到“虚拟”LocationPicker(绑定到我的viewmodel)时,它可以工作。 如何将LocationTreeView绑定到我的viewmodel?

public partial class LocationTreeView: UserControl
{
    public EventHandler LocationChanged;
    ...

    public static readonly DependencyProperty SelectedLocationProperty = 
         DependencyProperty.Register("SelectedLocation",typeof(Location), typeof(LocationTreeView),
         new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, SelectedLocationChanged));
    ...

    public static void SelectedLocationChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
         LocationTreeView sender = (d as LocationTreeView);
         Location loc = e.NewValue as Location;
         //Navigate the treeview to the selected location
         sender.LoadLTreeViewPathToLocation(loc);
    }

    public Location SelectedLocation
    {
         get { return (Location)GetValue(SelectedLocationProperty); }
         set
         {
              if (SelectedLocation != value)
              {
                 SetValue(SelectedLocationProperty, value);
                 if (LocationChanged != null)
                 {
                     LocationChanged(this, EventArgs.Empty);
                 }
              }
         }
    }
    ...
}

绑定到此控件时,绑定到另一个控件时可以正常工作,但绑定到我的viewmodel时则不行。我在SelectedLocationChanged回调中设置了一个断点,当我设置viewmodel属性(它实现了INotifyPropertyChanged)时它似乎没有被触发

public partial class LocationPicker: UserControl
{
    public static readonly DependencyProperty SelectedLocationProperty = 
         DependencyProperty.Register("SelectedLocation",typeof(Location), typeof(LocationPicker),
         new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
    ...

    public Location SelectedLocation
    {
         get { return (Location)GetValue(SelectedLocationProperty); }
         set { SetValue(SelectedLocationProperty, value); }
    }
    ...

    private void Button_Click(object sender, RoutedEventArgs e)
    {
         // create a window with a locationtreeview on it. Set the treeview's
         // selectedlocation property, open the window, wait for the window to close,
         //  set this.SelectedLoctation to the treeview's selected location.
    }
}

我为遗漏这么多代码而道歉。我的工作环境使我无法复制/粘贴。

我遗漏了ViewModel的代码。我非常有信心这不是问题。


更新: LocationTreeView具有在xaml

中设置的ViewModel
<UserControl.DataContext>
    <VM:LocationTreeViewViewModel />
</UserControl.DataContext>

LocationPicker没有ViewModel。 在我使用控件的窗口上,xaml看起来像这样

<Widow.DataContext>
    <VM:TestWindowViewModel />
</Window.DataContext>
<Grid>
...
<UC:LocationPicker x:Name="picker" SelectedLocation="{Binding Location}" /> 

<!-- this does not work -->
<UC:LocationTreeView SelectedLocaiton="{Binding Location}" />

<!-- but this works --->
<UC:LocationTreeView SelectedLocaiton="{Binding SelectedLocation, ElementName=picker}" />
...
</Grid>

1 个答案:

答案 0 :(得分:0)

如果要将视图模型中的数据绑定到LocationTreeView,则应使用视图模型中的属性来绑定数据。如果您的视图模型中有一个名为SelectedLocationInViewModel的属性,那么您应该将其用于数据绑定到:

<UC:LocationTreeView SelectedLocation="{Binding SelectedLocationInViewModel}" />

我认为我现在看到你的问题了......你想在UserControl中定义一些属性并将数据绑定到它们,但数据绑定到属性查看设置为DataContext的模型。您需要使用RelativeSource Binding来执行此操作...只需查看以下示例中的Binding Path

将数据绑定到UserControlUserControl 中声明的属性:

<ItemsControl ItemsSource="{Binding PropertyName, RelativeSource={RelativeSource 
    AncestorType={x:Type YourPrefix:YourUserControl}}}" />

将数据绑定到在任何对象集中声明的属性DataContext

<ItemsControl ItemsSource="{Binding PropertyName}" />