Группа ToggleButton с проверкой нуля или одной кнопки переключения - PullRequest
0 голосов
/ 28 февраля 2012

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

Если я использую радиокнопку со стилем тумблера, то по крайней мере одна тумблер будет проверяться в определенное время, и я хочу разрешить опцию, чтобы никакая тумблер не проверялась.

Я создал следующий стиль для кнопки-переключателя и следующих кнопок-переключателей, но по какой-то причине кнопка не изменяет свойство ischecked при вызове.

<Window x:Class="ClearMvvmDeltaItem.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:Model="clr-namespace:ClearMvvmDeltaItem.Model" Title="MainWindow"
    Height="300"
    Width="300"
    DataContext="{Binding Main, Source={StaticResource Locator}}">
<Window.Resources>
    <Model:NotConverter x:Key="NotConverter" />
    <Style TargetType="{x:Type CheckBox}">
        <Style.Triggers>
            <DataTrigger Value="False">
                <DataTrigger.Binding>
                    <MultiBinding Converter="{StaticResource NotConverter}" UpdateSourceTrigger="PropertyChanged">
                        <Binding RelativeSource="{RelativeSource Mode=Self}" Path="Name"></Binding>
                        <Binding Path="CurrentCheckedItem"></Binding>
                    </MultiBinding>
                </DataTrigger.Binding>
                <DataTrigger.Setters>
                    <Setter Property="Background" Value="Red"></Setter>
                    <Setter Property="IsChecked" Value="False"></Setter>
                </DataTrigger.Setters>
            </DataTrigger>
        </Style.Triggers>
    </Style>
</Window.Resources>
<Grid x:Name="LayoutRoot">
    <Grid.RowDefinitions>
        <RowDefinition></RowDefinition>
        <RowDefinition></RowDefinition>
        <RowDefinition></RowDefinition>
    </Grid.RowDefinitions>
    <CheckBox x:Name="first"  Content="First"
                  Command="{Binding FirstCheckedChanged}"  CommandParameter="{Binding RelativeSource={RelativeSource Mode=Self}, Path=Name}" 
                  IsChecked="{Binding IsFirstChecked }" 
                  >

    </CheckBox>
    <CheckBox x:Name="second" Command="{Binding SecondCheckedChanged}"  CommandParameter="{Binding RelativeSource={RelativeSource Mode=Self}, Path=Name}" 
                  IsChecked="{Binding IsSecondChecked}"
                  Content="Second" 
                  Grid.Row="1"></CheckBox>
        <CheckBox x:Name="third" Content="Third" Grid.Row="2"
                  Command="{Binding ThirdCheckedChanged}"  CommandParameter="{Binding RelativeSource={RelativeSource Mode=Self}, Path=Name}" 
                  IsChecked="{Binding IsThirdChecked}"
                  ></CheckBox>
</Grid>

Код команды Viewmodel:

FirstCheckedChanged = new RelayCommand<string>(newName =>
        {
            if (_isFirstChecked)
                CurrentCheckedItem = newName;
        });
        SecondCheckedChanged = new RelayCommand<string>(newName =>
        {
            if (_isSecondChecked)
                CurrentCheckedItem = newName;
        });
        ThirdCheckedChanged = new RelayCommand<string>(newName =>
        {
            if (_isThirdChecked)
                CurrentCheckedItem = newName;
        });

Источник данных вызывается, потому что я вижу, что цвет фона соответствующих кнопок переключения изменился на красный, но свойство ischecked вообще не затронуто.

Спасибо ...

Ответы [ 3 ]

2 голосов
/ 28 февраля 2012

Лично я бы использовал ListBox и стилизовал бы его так, чтобы элементы были ToggleButtons

<Style x:Key="ToggleButtonListBoxStyle" TargetType="{x:Type ListBox}">
    <Setter Property="BorderBrush" Value="Transparent"/>
    <Setter Property="KeyboardNavigation.DirectionalNavigation" Value="Cycle" />
    <Setter Property="ItemContainerStyle">
        <Setter.Value>
            <Style TargetType="{x:Type ListBoxItem}" >
                <Setter Property="Margin" Value="2, 2, 2, 0" />
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate>
                            <Border Background="Transparent">
                                <ToggleButton Content="{TemplateBinding ContentPresenter.Content}"  
                                    IsChecked="{Binding Path=IsSelected,RelativeSource={RelativeSource TemplatedParent},Mode=TwoWay}"/>
                            </Border>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </Setter.Value>
    </Setter>
</Style>

<ListBox ItemsSource="{Binding MyOptions}"
         SelectedItem="{Binding CurrentCheckedItem}"
         Style="{StaticResource ToggleButtonListBoxStyle}"/>

Это позволит включать только одну кнопку за раз, и вы можете сделать CurrentCheckedItem равно null снятием отметки с выбранного ToggleButton.

Это также немного очистит ваш код, потому что вам не нужно отслеживать 3 отдельных RelayCommands, чтобы отслеживать изменения выбора.

В качестве примечания, ваш исходный код не работает, потому что свойство, установленное в <Tag> элемента управления, имеет приоритет над свойством, установленным в DataTrigger.Чтобы это работало, вам нужно установить значение по умолчанию (привязку) как установщик в <Style>.Подробнее о приоритете свойства зависимости можно узнать здесь .

1 голос
/ 25 сентября 2013

Программирование строгого MVVM не всегда возможно .. ничего плохого в небольшом обходном пути здесь и там. Вот как я это решил (без использования радиокнопок или списка). Это вызывается из общего события щелчка переключателя, передавая имя кнопки:

    private void ToggleToolBarButtons(string button)
    {
        foreach (Object o in this.stkToolBar.Children)
        {
            if (o.GetType() == typeof(ToggleButton))
            {
                ToggleButton t = o as ToggleButton;
                if (t.Name != button)
                    t.IsChecked = false;
                else
                    t.IsChecked = true;
            }
        }
    }
0 голосов
/ 28 февраля 2012

Я считаю, что если вы применяете определенное значение к свойству IsChecked вашего флажка в его определении (которое вы сделали с помощью этой привязки), то значение, которое вы пытаетесь применить с помощью своего стиля, игнорируется.

Учитывая, что все ваши флажки привязаны к свойствам модели представления, вероятно, было бы проще всего обновить их, просто обновив эти свойства модели представления, а не используя триггер.Таким образом, если для свойства FirstCheckboxChecked установлено значение true, свойства SecondCheckboxChanged и ThirdCheckboxChanged также будут иметь значение false, что будет передаваться самим флажкам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...