WPF: boolean value binding - в чем может причина InvalidCastException?

Всем привет. Ситуация: имеется приложение, использующее .NET framework 4.8 (это VSTO-аддон, поэтому .NET Core использовать нельзя). У приложения имеется интерфейс на WPF, в составе которого в т.ч. есть ComboBox с самописным шаблоном (ControlTemplate). На компьютере, где ведется разработка, всё работает вполне нормально, однако на нескольких прочих обнаружилось, что ComboBox в нередактируемом состоянии (он только в таком и присутствует) раскрывает Popup со списком элементов только со 2-3-го клика мышью (на компьютере разработки это происходит сразу). Шаблон ComboBox привносит только визуальные украшательства, функционально он практически ничем не отличается от стандартного - в том числе и в части связи ToggleButton.IsChecked - ComboBox.IsDropDownOpen:

  <Grid x:Name="templateRoot" SnapsToDevicePixels="true">
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="*"/>
      <ColumnDefinition Width="38"/>
    </Grid.ColumnDefinitions>
    <ToggleButton
      x:Name="toggleButton"
      Grid.Column="0"
      Grid.ColumnSpan="2"
      BorderBrush="{TemplateBinding BorderBrush}"
      Background="{TemplateBinding Background}"
      BorderThickness="{TemplateBinding BorderThickness}"
      IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
      ..............

ToggleButton нормально нажимается, триггеры её стиля корректно обрабатывают установку свойства IsChecked - это видно визуально. Однако, как выяснилось, проблемы именно в этой связи - на компьютерах, где происходит вышеупомянутое неправильное поведение, в окне XAML Binding Failures появляется такая ошибка:

Cannot save value from target back to source. BindingExpression:Path=IsDropDownOpen; DataItem='ComboBox' (Name='');
target element is 'ToggleButton' (Name='toggleButton'); target property is 'IsChecked' (type 'Nullable``1``')
InvalidCastException: Заданное приведение является недопустимым.

Учитывая, что свойство ComboBox.IsDropDownOpen имеет тип bool, а свойство ToggleButton.IsChecked имеет тип Nullable<bool>, я попробовал в binding'е использовать конвертер (хотя за всё мое время работы с WPF внутренние механизмы data binding такое приведение типов нормально обрабатывали сами):

public class TestConverter: IValueConverter
{
  public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    => (bool?)(value is true); // здесь targetType=Nullable<bool>
  public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    => value is true; // здесь targetType=bool
}

-- эффекта ноль, всё та же ошибка. Установка свойств IsThreeState=False и IsChecked=False в шаблоне для ToggleButton никакого эффекта не возымели.

Тогда было решено пойти совсем другим путём (при всем осознании его неправильности) - был написан attached behavior для ToggleButton, который устанавливает свойства ToggleButton.IsChecked и ComboBox.IsDropDownOpen по событиям TaoggleButton.Click, ComboBox.DropDownOpened, и ComboBox.DropDownClosed.

Здесь случилось самое интересное - чтобы не перебивать binding к ComboBox.IsDropDownOpen, если он где-то есть в коде, я установку значения этого свойства решил сделать через SetCurrentValue:

ParentComboBox.SetCurrentValue(ComboBox.IsDropDownOpenProperty, AssociatedObject.IsChecked.GetValueOrDefault());

и именно в этот момент уже абсолютно явным образом, а не тихо в окне XAML Binding Failures, вылетает всё то же исключение InvalidCastException именно с таким же сообщением. Этот результат меня окончательно поставил в тупик - все типы здесь именно такие, какие требуются.

У себя на компьютере я всё это воспроизвести не смог - всё работает нормально и штатно, но лично видел всё вышеописанное по удалённому подключению.

И ещё смущает тот факт, что после первых двух неудачных попыток раскрытия, с третьей Popup начинает раскрываться нормально, и далее раскрывается по первому клику мышью до закрытия окна, содержащего ComboBox - как будто после третьей попытки что-то в инфраструктуре DataBinding налаживается, и начинает работать так, как положено.

Кто-нибудь сталкивался с подобным? В чем может быть причина такого поведения? Спасибо.


Ответы (0 шт):