我正在尝试绑定到用户控件的属性,但它似乎不起作用。
<Controls:BasicFilter Title="Some title" FilterLists="{Binding LocationFilterLists}"/>
FilterLists
是我要绑定的属性。 Title属性包含一个文本,显示在我的控件中的标签上,这很有效。
我已经设置了一个基本的ViewModel,它尝试设置LocationFilterLists
。因为它绑定到我的控件的FilterLists
属性,我希望这会将该值设置为该属性,但这不会发生。这是我的ViewModel的代码:
public class MainViewModel : DependencyObject
{
public NamedListList LocationFilterLists
{
get { return (NamedListList)GetValue(LocationFilterListsProperty); }
set { SetValue(LocationFilterListsProperty, value); }
}
public static readonly DependencyProperty LocationFilterListsProperty =
DependencyProperty.Register("LocationFilterLists", typeof(NamedListList), typeof(MainViewModel), new PropertyMetadata(null));
public MainViewModel()
{
}
internal void Refresh()
{
NamedListList nll = new NamedListList();
NamedList nl1 = new NamedList();
nl1.Name = "filter1";
NamedList nl2 = new NamedList();
nl2.Name = "filter2";
nll.Add(nl1);
nll.Add(nl2);
LocationFilterLists = nll;
}
}
NamedList
继承自List<object>
并添加了一个属性Name
,NamedListList
继承自List<NamedList>
。我将视图设置为在DataContext设置为此ViewModel后立即调用Refresh
方法。
这是我的对手的XAML:
<UserControl x:Class="Plin.CommonDisplayObjects.Controls.BasicFilter"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d">
<Grid Background="Gray">
<DockPanel x:Name="dockPanel" Margin="3">
<Label Content="{Binding Title}" DockPanel.Dock="Top" Margin="0" Padding="5,3,5,3"/>
</DockPanel>
</Grid>
</UserControl>
这是我控制的代码隐藏:
public partial class BasicFilter : UserControl
{
#region Dependency Properties
public string Title
{
get { return (string)GetValue(TitleProperty); }
set { SetValue(TitleProperty, value); }
}
public static readonly DependencyProperty TitleProperty =
DependencyProperty.Register("Title", typeof(string), typeof(BasicFilter), new PropertyMetadata(""));
public NamedListList FilterLists
{
get { return (NamedListList)GetValue(FilterListsProperty); }
set
{
SetValue(FilterListsProperty, value);
RegenerateFilter(); // Every time property is set, new buttons should be generated.
}
}
public static readonly DependencyProperty FilterListsProperty =
DependencyProperty.Register("FilterLists", typeof(NamedListList), typeof(BasicFilter), new PropertyMetadata(null));
#endregion
public BasicFilter()
{
InitializeComponent();
this.DataContext = this;
}
private void RegenerateFilter()
{
dockPanel.Children.Clear();
if (FilterLists != null)
{
foreach (NamedList nl in FilterLists)
{
Button b = new Button();
b.Content = "Some generic content " + nl.Name;
// set other properties on Button
dockPanel.Children.Add(b);
}
}
}
}
启动时,我的控件上会出现两个按钮,但在这种情况下不会出现任何按钮。我已尝试以编程方式设置FilterLists
属性(通过向ViewModel传递视图引用,命名我的控件和viewReference.myControl.FilterLists = nll;
),这样可行,但我更愿意能够如上所示进行绑定。我错过了什么?
答案 0 :(得分:1)
除了SetValue
之外,您不应该在依赖项属性的CLR包装器中执行任何操作,因为WPF可能会绕过包装器。有关详细信息,请参阅MSDN上的XAML Loading and Dependency Properties文章。
不必在setter中调用RegenerateFilter()
,而是必须使用依赖项属性元数据注册PropertyChangedCallback:
public NamedListList FilterLists
{
get { return (NamedListList)GetValue(FilterListsProperty); }
set { SetValue(FilterListsProperty, value); }
}
public static readonly DependencyProperty FilterListsProperty =
DependencyProperty.Register(
"FilterLists", typeof(NamedListList), typeof(BasicFilter),
new PropertyMetadata(null, FilterListsPropertyChanged));
private static void FilterListsPropertyChanged(
DependencyObject o, DependencyPropertyChangedEventArgs e)
{
((BasicFilter)o).RegenerateFilter();
}
也就是说,您的视图模型不应该从DependencyObject派生并声明依赖项属性。相反,它应该实现INotifyPropertyChanged
接口,并在必须通知集合更改时使用ObservableCollections。
编辑:由于BasicFilter构造函数中的语句this.DataContext = this;
,UserControl的DataContext设置为自身,而不是任何视图模型实例。因此绑定基础结构在UserControl中搜索绑定源属性LocationFilterLists
,当然不存在。
从BasicFilter构造函数中删除该行,并让UserControl从其父控件(自动工作)继承其DataContext。这假定DataContext例如是MainWindow设置在某个MainViewModel实例的位置。