簡體   English   中英

綁定到usercontrol中的依賴項屬性

[英]Binding to dependency property in usercontrol

我有一個包含一個ListBox的UserControl,我想跟蹤該列表框的SelectedItems。 UserControl有一個DP“ SelectedItemsList”,其定義如下

public static DependencyProperty SelectedItemsListProperty = DependencyProperty.Register(
  "SelectedItemsList",
  typeof (IList),
  typeof (MyListControl),
  new FrameworkPropertyMetadata(null, 
    OnSelectedItemsChanged));

在列表框的項目“ SelectionChanged”事件中,我想將所選項目保存到DP。 每當我更改列表框中的選擇時,都會觸發此操作。

private void OnItemSelectionChanged(object sender, SelectionChangedEventArgs e)
{
  SelectedItemsList = this.myListBox.SelectedItems;
}

在包含“ MyListControl”的視圖中,我創建了要使用所選項目的視圖模型的綁定。

 <controls:MyListControl 
  Source="{Binding SomeItemsList, UpdateSourceTrigger=PropertyChanged}"
  SelectedItemsList="{Binding SelectedItems, UpdateSourceTrigger=PropertyChanged}"/>

我的問題是,DP SelectedItemsList永遠不會更新。 DP的PropertyChangeCallback“ OnSelectedItemsChanged”僅在我最初加載列表內容時觸發。 SelectedItemsList的值始終為null。

我知道這個問題類似於Dependency屬性回調不起作用 ,但是在那里發布的答案不能解決我的問題。

我在這里想念什么?

謝謝,

編輯(2015-09-10):謝謝大家的評論。 我找到了適合我需求的解決方案:

首先,我創建了一個自定義列表框控件,該控件在依賴項屬性中提供了選定項目的列表(非常類似於從MVVM WPF項目中從DataGrid中選擇多個項目 )。

 public class CustomListBox : ListBox
 {
    public static readonly DependencyProperty SelectedItemsListProperty =
         DependencyProperty.Register("SelectedItemsList",
         typeof (IList),
         typeof (CustomListBox),
         new PropertyMetadata(null));

    public CustomListBox()
    {
       SelectionChanged += OnSelectionChanged;
    }

   public IList SelectedItemsList
   {
       get { return (IList)GetValue(SelectedItemsListProperty); }
       set { SetValue(SelectedItemsListProperty, value); }
   }

   void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
   {
      this.SelectedItemsList= new ArrayList(this.SelectedItems);
   }   
  }   

我對“ new ArrayList”部分還不滿意,但是如果在我的視圖模型的屬性設置器中我想檢查是否相等,則SelectedItemsList不能是SelectedItems的引用。 以前的值和新的值將始終相同。

然后,將UserControl“ MyListControl”的項目選擇部分簡化為依賴項屬性本身:

public static DependencyProperty SelectedItemsProperty =  DependencyProperty.Register(
  "SelectedItems",
  typeof (IList),
  typeof (MyListControl),
  new FrameworkPropertyMetadata(null));


public IList SelectedItems
{
  get
  {
    return (IList)GetValue(SelectedItemsProperty);
  }
  set
  {
    SetValue(SelectedItemsProperty, value);
  }
}

並修改了MyListControl的xaml:

  <controls:CustomListBox  
       SelectionMode="Extended" 
       ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type controls:MyListControl}},
       Path=Source, UpdateSourceTrigger=PropertyChanged}"           
       SelectedItemsList="{Binding RelativeSource={RelativeSource AncestorType={x:Type controls:MyListControl}},
       Path=SelectedItems, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
       >

我的ViewModel中的屬性看起來像

public IList SelectedObjects
{
  get { return _selectedObjects; }
  set { if (this._selectedObjects != value)
        {
          this._selectedObjects = value;
          OnPropertyChanged(SelectedObjectsProperty);
        }
       }
 }

此屬性的類型為IList非常重要,否則設置器中的值將始終為null。

在視圖的xaml中

<controls:MyListControl
  Source="{Binding CurrentImageList, UpdateSourceTrigger=PropertyChanged}"
  SelectedItems="{Binding SelectedObjects, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
 />

不幸的是,今天我遇到了同樣的問題,當您為SelectedItemsList分配一個值時,WPF似乎將其取消綁定。 為了解決這個問題,我更新了綁定項目中的值。 我知道這不是世界上最好的解決方案,但對我而言,它是有效的。 在這種情況下,代碼如下所示:

private void OnItemSelectionChanged(object sender, SelectionChangedEventArgs e)
{
    this.SetPropertyValue(
    this.GetBindingExpression(SelectedItemsListProperty), 
                this.myListBox.SelectedItems);
}


    private void SetPropertyValue(BindingExpression bindingExpression, object value)
    {
        string path = bindingExpression.ParentBinding.Path.Path;

        var properties = new Queue<string>(
            path.Split(
                new[]
                    {
                        '.'
                    }).ToList());

        this.SetPropertyValue(bindingExpression.DataItem, bindingExpression.DataItem.GetType(), properties, value);
    }



    private void SetPropertyValue(object destination, Type type, Queue<string> properties, object value)
    {
        PropertyInfo property = type.GetProperty(properties.Dequeue());

        if (property != null && destination != null)
        {
            if (properties.Count > 0)
            {
                this.SetPropertyValue(property.GetValue(destination), property.PropertyType, properties, value);
            }
            else
            {
                property.SetValue(destination, value);
            }
        }
    }

您需要將列表框的SelectedItems綁定到DP SelectedItemsList,以將用戶選擇傳播到DP。 然后,您已經擁有的綁定將把更改傳遞給viewmodel,但是我認為您將需要綁定模式“雙向”而不是UpdateSourceTrigger。

並且不要在DP中使用PropertyChangeCallback:如果SelectedItemsListProperty發生了更改,則更改SelectedItemsList是沒有意義的。 (通常,前者是后者的包裝器屬性。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM