繁体   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