【发布时间】:2014-08-18 20:57:34
【问题描述】:
我有两个用户控件:一个 LocationTreeView 和一个 LocationPicker。 LocationTreeView 将 Locations 组织成一个树形结构。由于涉及的位置数量众多,一次只加载树的一部分(随着项目的展开,一次加载一级)。
LocationPicker 只不过是一个带有按钮的文本块,它可以打开一个带有 LocationTreeView 的模式窗口。
当我将 LocationPicker 的“SelectedLocation”属性绑定到我的 Viewmodel 时,它可以正常工作。当我将 LocationTreeView 绑定到视图模型时,绑定似乎根本没有任何效果。当我将 LocationTreeView 绑定到“虚拟”LocationPicker(绑定到我的视图模型)时,它可以工作。 如何让我的 LocationTreeView 绑定到我的视图模型?
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);
}
}
}
}
...
}
绑定到另一个控件时,此控件上的绑定可以正常工作,但绑定到我的视图模型时则不行。我在 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>
【问题讨论】:
-
能否请您出示Binding的代码?
-
直到明天我才能验证这一点,但我认为问题在于,当 LocationTreeView 绑定到视图模型时,它使用 LocationTreeView 的默认 DataContext 而不是窗口的 DataContext。这可以解释为什么它在绑定到另一个控件时会起作用,因为在绑定表达式中设置 ElementName(或 RelativeSource 等)会显式设置该表达式的 DataContext。
标签: c# wpf xaml mvvm user-controls