Reputation: 663
I am a traditional MVC programmer that just started using MVVM and I do not know how I would program the below scenario the MVVM-way. I probably need multi binding, but can someone please help me and write that code for me? I've spend hours trying to achieve this, but I just don't know how to do it...
Btw, I know how to set the values from my settings file in XAML, but don't know how to write the other logic, EG:
IsEnabled="{Binding Source={x:Static p:Settings.Default}, Path=Pref_QuickProcess}"
This is my scenario:
I have a simple preferences screen with two checkboxes:
□ Quick process (value is set from Settings.Default.Pref_QuickProcess)
□ Upload to youtube (value is set from Settings.Default.Pref_UploadToYoutube)
The following conditions apply:
These are the only options:
This is my 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>
This is my code behind:
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);
}
}
How do I get rid of my code behind, and get the same result in XAML with things like data triggers, converters, multi binding?
Edit: I think I do not necessarily need a viewmodel with setters to implement this logic, and do it with data triggers ? / multi binding ? instead. But maybe that is not possible?
Upvotes: 3
Views: 2297
Reputation: 128061
You probably don't need a view model just to set a few properties in the Settings class that have a certain interdependence. The following XAML should do most or perhaps all of what you are describing.
When the first Checkbox is checked, the IsChecked
and IsEnabled
properties of the second Checkbox are set to false. However, the Settings.Default.Pref_UploadToYoutube
property value is not changed. Not sure if this is strictly required.
By default, the second CheckBox's IsChecked
property is bound to Pref_UploadToYoutube
via a Style Setter. A DataTrigger on the Pref_QuickProcess
property replaces the Binding and sets IsChecked
and IsEnabled
to false.
Also note the new Binding Path syntax for binding to static properties.
<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>
You may also simplify the Settings properties binding paths by assigning the Settings.Default
instance once to the DataContext of the StackPanel parent of the CheckBoxes:
<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>
Upvotes: 3