我正在开发自定义控件。我希望它支持数据绑定,因此它与内置控件一样易于维护。
这是我到目前为止所得到的:
包含我的控件的Window.xaml代码窗口:
<custom:Matrix x:Name="customMatrix" DockPanel.Dock="Top" Title="{Binding Title}"/>
...及其Window.xaml.cs代码隐藏(只是视图模型的一个片段)
public ViewModel VM { get; private set; }
private ProblemManager()
{
VM = new ViewModel();
InitializeComponent();
DataContext = VM;
VM.Title = "a title";
}
public class ViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public ViewModel()
{
ItemsList = new ObservableCollection<List<int>>();
}
public ObservableCollection<List<int>> ItemsList { get; set; }
protected string title;
public string Title
{
get { return title; }
set
{
if (title != value)
{
title = value;
NotifyPropertyChanged("Title");
}
}
}
protected void NotifyPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
我的控件Matrix.xaml
// ...
<TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Title}"/>
// ...
和控件的Matrix.xaml.cs代码隐藏
public partial class Matrix : UserControl
{
public Matrix()
{
InitializeComponent();
DataContext = this;
}
public static readonly DependencyProperty TitleProperty =
DependencyProperty.Register("Title", typeof(string), typeof(Matrix), new PropertyMetadata("", TitleChanged));
public string Title
{
get { return (string)GetValue(TitleProperty); }
set { SetValue(TitleProperty, value); }
}
private void TitleChanged(string title)
{
Title = title;
}
private static void TitleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((Matrix)d).TitleChanged((string)e.NewValue);
}
}
事情是,如果我的窗口xaml没有绑定到Matrix.Title
属性,即在xaml中静态地给出该值,如Title="some title"
,我的控制代码中的绑定可以正常工作(我甚至可以{{ 1}}在我的窗口,它的工作原理)。但是,当绑定到customMatrix.Title += "1";
属性时(就像我在提供的代码中所做的那样),它不起作用,我在视图中得到一个空白标题。只是清楚地说明,绑定到窗口中的默认控件。
如何使 Matrix.Title
属性可绑定?
答案 0 :(得分:2)
Matrix控件上的TextBlock绑定错误。
您已经设置了依赖项属性,然后Window.xaml中的代码将该属性绑定到Window类中的Title。虽然你不需要TitleChanged功能(绑定会自动完成,所以你不需要自己手动完成),那部分都很好。问题是UserControl中的TextBlock.Text属性声明如下:
<TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Title}"/>
所以它试图绑定到UserControl的当前DataContext,如果你没有设置它(你显然没有),那么它从MainWindow继承它,它可能是也可能不是你想要它。要解决此问题,您需要将TextBlock绑定到 UserControl的属性,而不是DataContext属性,并使用FindAncester执行此操作:
<TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type custom:Matrix}}, Path=Title}" />
更新:另一种方法是给Matrix.xaml文件中的UserControl一个名称并使用ElementName绑定它:
<UserControl x:Class="YourProjectNameHere.Matrix"
xmlns:custom="clr-namespace:Wpftest2"
... more namespaces here
mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300"
Name="thisControl">
<Grid>
<TextBlock Name="theTextBlock" Grid.Row="0" Grid.Column="1" Text="{Binding ElementName=thisControl, Path=Title}"/>
</Grid>