Свойство зависимости CollectionType - PullRequest
0 голосов
/ 11 августа 2010

На основе этого урока:

http://www.dotnetfunda.com/articles/article961-wpf-tutorial--dependency-property-.aspx

Я создал свой пользовательский контроль следующим образом:

usercontrol xaml:

 <UserControl x:Class="PLVS.Modules.Partner.Views.TestControl"
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       xmlns:tp="http://thirdparty.com/controls"
       x:Name="UC">
  <tp:ContainerControl x:Name="tpControl">
    <tp:ContainerControl.Items>
      <tp:SomeItem SomeProperty="SomeValue">
        <TextBlock Text="SomeText"/>
      </tp:SomeItem>
    </ig:TabItemEx>
 </tp:ContainerControl.Items>
  </tp:ContainerControl>
</UserControl> 

код контроля пользователя:

public partial class TestControl : UserControl
{
 public TestControl()
    {
  InitializeComponent();
  SetValue(TestItemsPropertyKey, new ObservableCollection<ThirdPartyClass>());
 }

    public ObservableCollection<ThirdPartyClass> TestItems
    {
      get 
      { 
        return (ObservableCollection<ThirdPartyClass>)GetValue(TabItemsProperty); 
      }
    }

    public static readonly DependencyPropertyKey TestItemsPropertyKey =
      DependencyProperty.RegisterReadOnly("TestItems", typeof(ObservableCollection<ThirdPartyClass>), typeof(TestControl), new UIPropertyMetadata(new ObservableCollection<ThirdPartyClass>(), TestItemsChangedCallback));

 public static readonly DependencyProperty TestItemsProperty = TestItemsPropertyKey.DependencyProperty;

 private static void TestItemsChangedCallback(DependencyObject obj, DependencyPropertyChangedEventArgs e)
 {
      TestControl ib = obj as TestControl;
  var newNvalue = e.NewValue; // Why is e.NewValue null???
 }
 }

Позже я хочу использовать контроль пользователя следующим образом:

 <localControl:TestControl x:Name="testControl">
 <localControl:TestControl.TabItems>
      <tp:SomeItem SomeProperty="SomeValue">
        <TextBlock Text="SomeText2"/>
      </tp:SomeItem>
  <tp:SomeItem SomeProperty="SomeValue">
        <TextBlock Text="SomeText3"/>
      </tp:SomeItem>
 </tp:ContainerControl.Items>
 </localControl:TestControl>

В приведенном выше коде яЯ добавил функцию обратного вызова в мой usercontrol, чтобы я мог добавить новые элементы в элемент управления контейнера "tpControl", объявленный в xaml.Однако, когда вызывается функция обратного вызова, новое значение остается пустым.И вопрос здесь почему?

1 Ответ

0 голосов
/ 12 августа 2010

Вы действительно видите e.NewValue как ноль или как пустую коллекцию?

В своем коде вы устанавливаете значение по умолчанию для свойства для экземпляра ObservableCollection (что обычно не следует делать для ссылочных типов - просто используйте null), а затем назначаете другой экземпляр ObservableCollection в конструкторе экземпляра вашего элемента управления, который вызывает измененный обратный вызов. Теперь вы назначаете новую пустую коллекцию, которую вы должны увидеть для e.NewValue.

Если вы хотите получить доступ к элементам, объявленным в XAML, вам нужно подождать, пока они не будут добавлены в коллекцию. Добавление элементов не вызовет срабатывания обработчика изменения свойства, поскольку вы не назначаете новую коллекцию для DP. Вы можете использовать обработчик для другого события, которое происходит позже (например, Loaded)

    Loaded += (sender, e) => { DoSomething(TestItems) };

или прикрепите обработчик CollectionChanged к экземпляру e.NewValue, который будет вызываться каждый раз, когда элемент добавляется, удаляется, перемещается и т. Д.

    var newValue = e.NewValue as ObservableCollection<ThirdPartyClass>;
    newValue.CollectionChanged += (sender, args) => { DoSomething(TestItems); };
...