2013-12-04 2 views
0

Я работаю над настраиваемым элементом управления. Я хочу, чтобы он поддерживал привязку данных, поэтому его легко поддерживать, как встроенные элементы управления.Привязка к пользовательскому свойству настраиваемого свойства управления не работает

Вот что я получил до сих пор:

  • окно Window.xaml код, который содержит мой контроль:

    <custom:Matrix x:Name="customMatrix" DockPanel.Dock="Top" Title="{Binding Title}"/> 
    
  • ... и его Window.xaml.cs код- за (всего фрагмента ViewModel)

    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", привязка внутри моего кода управления работает (я могу даже сделать customMatrix.Title += "1"; в моем окне, и он работает). Однако при привязке к свойству Matrix.Title (как и в приведенном коде) он не работает, и я получил пустой заголовок на мой взгляд. Чтобы четко сформулировать это, работает привязка к элементам управления по умолчанию в окне.

Как сделатьMatrix.Title Недвижимость можно использовать?

ответ

1

Неправильное привязку TextBlock к управлению вашей матрицей.

Вы создали свойство зависимостей, а затем код в вашем Window.xaml связывает это свойство с заголовком в вашем классе Window. Эта часть все в порядке, хотя вам не нужна функция TitleChanged (привязка выполняется автоматически, поэтому вам не нужно делать это вручную самостоятельно). Проблема заключается в том, что свойство TextBlock.Text в вашем UserControl объявлен как это:

<TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Title}"/> 

Так он пытается связать с текущим DataContext в UserControl, и если вы не установили, что (который вы, по-видимому не), то он наследует его от 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}" /> 

ОБНОВЛЕНО: Еще один способ сделать это, чтобы дать UserControl в вашей матрице .xaml файл имя и привязать к нему с 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> 

+0

не указав DataContext моего контроля сделано в 'конструктору Matrix' по' DataContext = это; '? – patryk

+0

Doh! Я даже не видел этого :) Но да, это ваша проблема прямо там, вы не можете просто изменить DataContext, чтобы указать на то, что вы хотите, потому что оно становится измененным из-под вас при размещении в главном окне.Избавьтесь от функции TitleChanged, удалите эту строку, которая назначает контекст данных в вашем пользовательском элементе управления и использует использование привязки FindAncestor, и это устранит вашу проблему. –

+0

Вы говорите, что назначение «DataContext = this;» не имеет никакого эффекта, когда я использую элемент управления где-то еще? Во всяком случае, я пытаюсь сделать то, что вы мне сказали. Помещение этого объявления привязки в Matrix.xaml дает мне ошибку, что 'custom' не определен. В действительности это не так, потому что я использую 'custom' как мое пространство имен xaml в Window.xaml. Я также старался иметь «x: Type Matrix» без везения. Что мне сейчас не хватает? – patryk

Смежные вопросы