У меня проблема с пользовательским 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 внутри элемента управления имеет правильное значение, но снаружи в коде установленное значение свойства равно нулю.
Что может быть не так?
Спасибо.
UPDATE:
Вот код, который изменяет 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 <<1023 * object </em>> '.
Спасибо за помощь.
">
Ситуация стека вызовов
Здесь виден счетчик всего шага назад в стеке вызовов.
Следующий шаг стека вызовов - точка останова - значение равно нулю
Правда в том, что между этими шагами есть какой-то внешний код - но я не получил ни ошибки, ни предупреждения
ОБНОВЛЕНИЕ - некоторый прогресс
Я пытался изменить общедоступный IEnumerable <<em> Driver > 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 использовать универсальный IEnumerable <<em> object >
Важно то, что IEnumerable <<em> object > хорошо работает с простым связыванием (в данном случае ItemsSource - true, это просто привязка OneWay)