«Цепная» привязка WPF

#.net #wpf #wpf-controls #binding

#.net #wpf #wpf-элементы управления #привязка

Вопрос:

Я создаю пользовательский элемент управления в WPF, который я называю YesNoButton.

Она имеет единственное свойство DependencyProperty, проверенное IsChecked, и содержит две кнопки переключения с метками «Да» и «Нет». Я привязал свойство IsChecked кнопки переключения Yes к этому свойству IsChecked родительского YesNoButton. Я привязал свойство IsChecked кнопки переключения No к свойству IsChecked кнопки переключения Yes с помощью ‘обратного логического значения’ IValueConverter. Вот моя разметка YesNoButton, за вычетом некоторых излишеств во внешнем виде:

 <UserControl ...>
    <StackPanel Orientation="Horizontal">
        <ToggleButton x:Name="YesButton" IsChecked="{Binding RelativeSource={RelativeSource AncestorType={x:Type Controls:YesNoButton}}, Path=IsChecked}">Yes</ToggleButton>
        <ToggleButton IsChecked="{Binding ElementName=YesButton, Path=IsChecked, Converter={StaticResource BooleanToInverseConverter}}">No</ToggleButton>
    </StackPanel>
</UserControl>
  

В моем приложении я включаю YesNoButton следующим образом:

 <local:YesNoButton IsChecked="{Binding Path=BoolPropertyOfDataContext}" />
  

При первой загрузке окна, если я переключаю BoolPropertyOfDataContext другими способами, YesNoButton реагирует идеально.

Но как только я нажимаю кнопку переключения «Да» или «Нет», хотя визуальное состояние YesNoButton обновляется правильно, привязка к BoolPropertyOfDataContext вообще перестает работать — похоже, она отменена. Я думал, что эти «цепочки привязок» должны были работать нормально, но я, очевидно, чего-то здесь не хватает!

Есть идеи?

Ответ №1:

Два предложения:

  1. Назовите свой UserControl, чтобы вы могли ссылаться на него
  2. Привязать оба состояния ToggleButton IsChecked к свойству IsChecked для UserControl

Например:

 <StackPanel Orientation="Horizontal">
    <ToggleButton IsChecked="{Binding ElementName=YesNoButton, Path=IsChecked}">Yes</ToggleButton>
    <ToggleButton IsChecked="{Binding ElementName=YesNoButton, Path=IsChecked, Converter={StaticResource BooleanToInverseConverter}}">No</ToggleButton>
</StackPanel>
  

Комментарии:

1. Спасибо. Уже пробовал (1) — никакой разницы. Я попытался полностью удалить переключатель No, но это все равно не сработало, поэтому я предполагаю, что (2) не поможет. Я знаю, что в прошлом, когда я вручную устанавливал свойству IsChecked элемента управления некоторое значение, его привязки были уничтожены. Я предполагаю, что здесь происходит нечто подобное, но я не могу понять, что.

2. Как реализован BoolPropertyOfDataContext? Является ли это свойством зависимости? Кроме того, замечаете ли вы какие-либо сообщения в окне вывода, если запускаете под управлением отладчика?

3. BoolPropertyOfDataContext — это логическое поле объекта Entity Framework Entity (и поэтому имеет уведомление об изменении свойства). К сожалению, в окне вывода нет сообщений!

4. Получилось совершенно по-другому (см. Мой отредактированный пост), но я до сих пор не знаю, почему моя первая попытка не сработала!

Ответ №2:

Я заставил это работать, установив вместо этого флажок:

 <CheckBox IsChecked="{Binding Path=BoolPropertyOfDataContext}" Style="{StaticResource YesNoButton}" />

<Style x:Key="YesNoButton" TargetType="{x:Type CheckBox}">
    <Setter Property="OverridesDefaultStyle" Value="True" />
    <Setter Property="SnapsToDevicePixels" Value="True" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type CheckBox}">

                <StackPanel Orientation="Horizontal">
                    <ToggleButton x:Name="YesButton" IsChecked="{Binding RelativeSource={RelativeSource AncestorType={x:Type CheckBox}}, Path=IsChecked}">Yes</ToggleButton>
                    <ToggleButton IsChecked="{Binding ElementName=YesButton, Path=IsChecked, Converter={StaticResource BooleanToInverseConverter}}">No</ToggleButton>
                </StackPanel>

            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>