[英]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.