绑定到自定义控件属性的自定义属性不起作用

时间:2013-12-04 00:05:17

标签: wpf data-binding wpf-controls custom-controls

我正在开发自定义控件。我希望它支持数据绑定,因此它与内置控件一样易于维护。

这是我到目前为止所得到的:

  • 包含我的控件的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 属性可绑定?

1 个答案:

答案 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>