Wpf 绑定到usercontrol中的依赖项属性
我有一个包含ListBox的UserControl,我想跟踪该ListBox的SelectedItems。 UserControl有一个DP“SelectedItemsList”,定义如下Wpf 绑定到usercontrol中的依赖项属性,wpf,binding,user-controls,dependency-properties,Wpf,Binding,User Controls,Dependency Properties,我有一个包含ListBox的UserControl,我想跟踪该ListBox的SelectedItems。 UserControl有一个DP“SelectedItemsList”,定义如下 public static DependencyProperty SelectedItemsListProperty = DependencyProperty.Register( "SelectedItemsList", typeof (IList), typeof (MyListControl)
public static DependencyProperty SelectedItemsListProperty = DependencyProperty.Register(
"SelectedItemsList",
typeof (IList),
typeof (MyListControl),
new FrameworkPropertyMetadata(null,
OnSelectedItemsChanged));
在listbox“Item“SelectionChanged”事件中,我想将所选项目保存到DP。每当我更改列表框中的选择时,就会触发此操作
private void OnItemSelectionChanged(object sender, SelectionChangedEventArgs e)
{
SelectedItemsList = this.myListBox.SelectedItems;
}
在包含“MyListControl”的视图中,我创建了一个要使用选定项的viewmodel绑定
<controls:MyListControl
Source="{Binding SomeItemsList, UpdateSourceTrigger=PropertyChanged}"
SelectedItemsList="{Binding SelectedItems, UpdateSourceTrigger=PropertyChanged}"/>
我对“new ArrayList”部分还不满意,但如果我想在viewmodel的属性设置器中检查是否相等,则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}"
>
此属性的类型必须为IList,否则setter中的值将始终为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);
}
}
}
private void OnItemSelectionChanged(对象发送方,SelectionChangedEventArgs e)
{
this.SetPropertyValue(
此.GetBindingExpression(SelectedItemsListProperty),
这个.myListBox.SelectedItems);
}
私有void SetPropertyValue(BindingExpression、BindingExpression、对象值)
{
字符串路径=bindingExpression.ParentBinding.path.path;
var属性=新队列(
路径,分开(
新[]
{
'.'
}).ToList());
this.SetPropertyValue(bindingExpression.DataItem,bindingExpression.DataItem.GetType(),属性,值);
}
私有void SetPropertyValue(对象目标、类型、队列属性、对象值)
{
PropertyInfo property=type.GetProperty(properties.Dequeue());
if(属性!=null&&destination!=null)
{
如果(properties.Count>0)
{
this.SetPropertyValue(property.GetValue(目标)、property.PropertyType、properties、value);
}
其他的
{
SetValue(目的地,值);
}
}
}
您需要将列表框的SelectedItems绑定到DP SelectedItems列表,以将用户选择传播到DP。然后,您已经拥有的绑定将把更改传递给viewmodel,但我认为您需要一个绑定模式“双向”,而不是UpdateSourceTrigger
不要在DP中使用PropertyChangeCallback:如果SelectedItemsListProperty已更改,则更改SelectedItemsList毫无意义。(通常前者是后者的包装属性。)在“OnItemSelectChanged”中的常规集之前添加“SelectedItemsList=null”时,可能会触发propertychangecallabck(对于两个集),但与我的ViewModel的绑定始终包含“null”.I仅使用PropertyChangeCallback来设置断点的位置,以查看是否发生任何更改。listbox没有SelectedItems属性的公共setter。因此,我无法创建对它的直接绑定。
<controls:MyListControl
Source="{Binding CurrentImageList, UpdateSourceTrigger=PropertyChanged}"
SelectedItems="{Binding SelectedObjects, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
/>
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);
}
}
}