WPF / XAML / MVVM-根据条件设置复选框的状态

时间:2018-10-26 21:48:22

标签: c# wpf xaml mvvm data-binding

我是一个传统的MVC程序员,刚开始使用MVVM,但我不知道如何以以下方式对MVVM进行编程。我可能需要多重绑定,但是有人可以帮助我并为我编写该代码吗?我已经花了很多时间尝试实现这一目标,但我只是不知道该怎么做...

顺便说一句,我知道如何从XAML中的设置文件中设置值,但是不知道如何编写其他逻辑,例如:

IsEnabled="{Binding Source={x:Static p:Settings.Default}, Path=Pref_QuickProcess}"

这是我的情况:

我有一个简单的偏好设置屏幕,其中有两个复选框:

□快速过程(通过Settings.Default.Pref_QuickProcess设置值)

□上载到youtube(值是通过Settings.Default.Pref_UploadToYoutube设置的)

以下条件适用:

  • 如果“快速处理”为true,则“上传至youtube”应始终设置为false,并且必须禁用。
  • 如果“快速处理”为假,则应启用“上传至youtube”。

这些是唯一的选择:

Examples

这是我的XAML:

<Window x:Class="SchismRecorder.PreferencesWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Title="Preferences" Height="450" Width="800">

<Grid>
    <GroupBox Header="Debug settings" HorizontalAlignment="Left" Height="326" Margin="21,20,0,0" VerticalAlignment="Top" Width="733">
        <StackPanel>
            <CheckBox Content="Quick process" HorizontalAlignment="Left" x:Name="chkQuickProcess" />
            <CheckBox Content="Upload to Youtube" HorizontalAlignment="Left" x:Name="chkUploadToYoutube" />
        </StackPanel>
    </GroupBox>
</Grid>

这是我后面的代码:

public partial class PreferencesWindow : Window
{
    public PreferencesWindow()
    {
        InitializeComponent();

        chkQuickProcess.IsChecked = Settings.Default.Pref_QuickProcess;
        chkUploadToYoutube.IsChecked = Settings.Default.Pref_UploadToYoutube;

        ConfigureCheckboxes();

        chkQuickProcess.Click -= ChkQuickProcess_Click;
        chkQuickProcess.Click += ChkQuickProcess_Click;
    }

    private void ChkQuickProcess_Click(object sender, RoutedEventArgs e)
    {
        ConfigureCheckboxes();
    }

    void ConfigureCheckboxes()
    {
        if (chkQuickProcess.IsChecked.HasValue)
        {
            var isChecked = chkQuickProcess.IsChecked.Value;

            if (isChecked)
            {
                chkUploadToYoutube.IsChecked = false;
                chkUploadToYoutube.IsEnabled = false;
            }
            else
            {
                chkUploadToYoutube.IsEnabled = true;
            }
        }
    }

    protected override void OnClosing(CancelEventArgs e)
    {
        Settings.Default.Pref_QuickProcess = chkQuickProcess.IsChecked ?? false;
        Settings.Default.Pref_UploadToYoutube = chkUploadToYoutube.IsChecked ?? false;
        Settings.Default.Save();

        base.OnClosing(e);
    }
}

如何摆脱我的代码,并在XAML中通过数据触发器,转换器,多重绑定之类的东西获得相同的结果?

编辑:我认为我不一定需要带有setter的viewmodel来实现此逻辑,并且不需要数据触发器吗? /多重绑定?代替。但这也许不可能吗?

1 个答案:

答案 0 :(得分:2)

您可能不需要视图模型,而只需要在Settings类中设置一些具有一定相互依赖性的属性。以下XAML应该可以完成您描述的大部分或全部任务。

选中第一个复选框时,第二个复选框的IsCheckedIsEnabled属性设置为false。但是,Settings.Default.Pref_UploadToYoutube属性值未更改。不确定是否严格要求。

默认情况下,第二个CheckBox的IsChecked属性通过样式设置器绑定到Pref_UploadToYoutubePref_QuickProcess属性上的DataTrigger替换了Binding,并将IsCheckedIsEnabled设置为false。

还请注意用于绑定到静态属性的新的Binding Path语法。

<CheckBox Content="Quick process"
          IsChecked="{Binding Path=(p:Settings.Default).Pref_QuickProcess}"/>

<CheckBox Content="Upload to Youtube">
    <CheckBox.Style>
        <Style TargetType="CheckBox">
            <Setter Property="IsChecked"
                    Value="{Binding Path=(p:Settings.Default).Pref_UploadToYoutube}"/>
            <Style.Triggers>
                <DataTrigger Binding="{Binding Path=(p:Settings.Default).Pref_QuickProcess}"
                             Value="True">
                    <Setter Property="IsChecked" Value="False"/>
                    <Setter Property="IsEnabled" Value="False"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </CheckBox.Style>
</CheckBox>

您还可以通过将Settings.Default实例分配一次给CheckBoxes的StackPanel父级的DataContext来简化Settings属性的绑定路径:

<StackPanel DataContext="{Binding Path=(p:Settings.Default)}">

    <CheckBox Content="Quick process" IsChecked="{Binding Pref_QuickProcess}"/>

    <CheckBox Content="Upload to Youtube">
        <CheckBox.Style>
            <Style TargetType="CheckBox">
                <Setter Property="IsChecked" Value="{Binding Pref_UploadToYoutube}"/>
                <Style.Triggers>
                    <DataTrigger Binding="{Binding Pref_QuickProcess}" Value="True">
                        <Setter Property="IsChecked" Value="False"/>
                        <Setter Property="IsEnabled" Value="False"/>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </CheckBox.Style>
    </CheckBox>
</StackPanel>