【发布时间】:2019-06-01 23:42:01
【问题描述】:
我的控件中的自定义 DependencyProperty 存在问题。让我解释一下:
我可以控制可检查项目的列表。我需要属性绑定到 IEnumerable SelectedItems。 SelectedItemsProperty 填充的逻辑在可控范围内,所以不只是简单的绑定。这是我控制的代码:
public static readonly DependencyProperty SelectedItemsProperty = DependencyProperty.Register("SelectedItems", typeof(IEnumerable<object>), typeof(ButtonColumnFilter));
public IEnumerable<object> SelectedItems
{
get { return (IEnumerable<object>)GetValue(SelectedItemsProperty); }
set { Debug.WriteLine("SelectedItems has been set in ButtonColumnFilter - Count:{0}", value?.Count());
SetValue(SelectedItemsProperty, value);
}
}
在这里,我收到带有正确数量的选定项目的调试消息,因此我的控制内部逻辑运行良好。 XAML 中的属性绑定在这里:
<MESControls:ButtonColumnFilter CanSearch="True" CanSort="False" DisplayMemberPath="DisplayName"
ItemsSource="{Binding Path=FilterAdapter.Drivers, Mode=OneWay, IsAsync=True}"
OnApplyFilter="Drivers_ApplyFilter"
SelectedItems="{Binding Path=SelectedFilterDrivers, Mode=TwoWay}"/>
并且属性是在我的代码中定义的:
public IEnumerable<Driver> SelectedFilterDrivers
{
get => _SelectedFilterDrivers;
set
{
Debug.WriteLine("SelectedFilterDrivers has been set in PlannerFilterAdapter - Count: {0}", value?.Count());
if (_SelectedFilterDrivers != value)
{
_SelectedFilterDrivers = value;
NotifyPropertyChanged("SelectedFilterDrivers");
}
}
}
!!!但是在这里我得到调试消息'value == null'!!!
绑定运行良好,并且我想可以及时正确调用属性集。奇怪的是,控件内部的 SetValue 具有正确的值,但在代码外部,属性设置值为 null。
有什么问题吗? 谢谢。
更新:
这是更改控件内部的 SelectedItems 的代码:
private void CheckableItem_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "IsChecked" && !_IsChecking)
{
_IsChecking = true;
CheckableItem item = sender as CheckableItem;
if(item.IsChecked == true && InnerItemsSource.Where(ci=>ci.Item.ToString() != SELECTALL).All(ci=>ci.IsChecked == true))
{
InnerItemsSource.Single(ci => ci.Item.ToString() == SELECTALL).IsChecked = true;
SelectAllIsSelected = true;
}
else if (InnerItemsSource.Where(ci => ci.Item.ToString() != SELECTALL).All(ci=>ci.IsChecked == true) || InnerItemsSource.Where(ci => ci.Item.ToString() != SELECTALL).All(ci => ci.IsChecked == false))
{
InnerItemsSource.Single(ci => ci.Item.ToString() == SELECTALL).IsChecked = false;
SelectAllIsSelected = false;
}
else
{
InnerItemsSource.Single(ci => ci.Item.ToString() == SELECTALL).IsChecked = null;
SelectAllIsSelected = false;
}
SelectedItems = CheckedItems;
NotifyPropertyChanged("IsFilterUsed");
NotifyPropertyChanged("FilterIcon");
}
_IsChecking = false;
}
public IEnumerable<object> CheckedItems
{
get
{
return InnerItemsSource?.Where(ci => ci.IsChecked == true && ci.Item.ToString() != SELECTALL).Select(ci => ci.Item);
}
}
但正如我所写,控件内设置的属性接收到正确的值,我猜是正确的类型。 CheckedItems 的返回值为 IEnumerable'object>'。
感谢您的帮助。
调用栈情况
调用栈的下一步——断点——值为null 事实是,这些步骤之间是一些外部代码 - 但我没有收到任何错误,也没有警告
更新 - 一些进展
我尝试将 public IEnumerableDriver> SelectedFilterDrivers 更改为
public IEnumerable<object> SelectedFilterDrivers
{
get => _SelectedFilterDrivers;
set
{
Debug.WriteLine("SelectedFilterDrivers has been set in PlannerFilterAdapter - Count: {0}", value?.Count());
if (_SelectedFilterDrivers != value)
{
_SelectedFilterDrivers = (IEnumerable<Driver>)value;
NotifyPropertyChanged("SelectedFilterDrivers");
}
}
}
我收到了正确数量的物品。因此,在重新键入集合中的项目期间存在问题。所以我需要以更好的方式继续前进,如何保持 SelectedItems 使用通用 IEnumerableobject>
的能力重要的是,IEnumerableobject> 与简单绑定配合得很好(在这种情况下 ItemsSource - true 是,它只是 OneWay 绑定)
【问题讨论】:
-
您的控件中是否有任何代码实际更改了
SelectedItems属性,即分配一个新的集合实例,或者您只是添加/删除项目?在后一种情况下,将属性绑定到 ObservableCollection。 -
你什么时候把你的属性设置在控制范围内?
-
已添加请求的代码。我总是添加新的集合实例。
-
它的赋值是否与绑定源属性兼容,即它是否是 Driver 对象的集合?
-
您可以在 SelectedFilterDrivers 设置器中放置一个条件断点(条件:
value==null),然后查看该调用的来源。
标签: c# wpf binding wpf-controls dependency-properties