GridView CheckBox binding - c#

How to change the value of a text block inside a grid view in WPF based on the check box selection . Grid view in WPF is populated from a sql table which has ID and Value as columns.Value here is YES or NO.I am using linq to sql .
I have a check box associated to each ID in the grid view.when a user selects some rows ,i have to save the changes back to the database.
So based on the selection i have to change the value field in the row in this fashion:
If the text in the "Value" field of the grid view is "YES" then i have to change it to "NO"
If the text in the "Value" field of the grid view is "NO" then i have to change it to "YES"
I am able to populate data into the gridview ,but i am not sure whether my questions in the above scenario will fit in WPF and c#.Need some guidance.

The best way to do this is to bind both the Text block and the checkbox to the same backend field in the data model and then to use code converters.
Here is a simple example.
Say you have the following simple view model with one bool property:
class SimpleViewModel: INotifyPropertyChanged
{
private bool _checked;
// The property to bind to
public bool Checked
{
get { return _checked; }
set { _checked = value; OnPropertyChanged("Checked"); }
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
Here is also a simple page with a text block and a text field that both bind to the same backend field.
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<local:SimpleViewModel x:Key="simpleViewModel" />
<local:BoolToStringConverter x:Key="boolToStringConverter" />
</Window.Resources>
<Grid DataContext="{StaticResource simpleViewModel}">
<StackPanel>
<TextBlock Text="{Binding Checked, Converter={StaticResource boolToStringConverter}}" />
<CheckBox Content="something" IsChecked="{Binding Checked}" />
</StackPanel>
</Grid>
</Window>
Now notice that the text block binding statement contains a converter statement.
Text="{Binding Checked, Converter={StaticResource boolToStringConverter}}"
The converter here is very simple. It checks the value if it's true and returns Yes, otherwise returns NO.
public class BoolToStringConverter:IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value == null) return null;
if ((bool)value == true)
return "YES";
else
return "NO";
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
// this scenario is not needed since the text block is read only
throw new NotImplementedException();
}
}

You need to do events. Click on the control and click the lightning bold and do it in the code behind in c#. The keyword is events. OnChanged, Onclicked, onrowchange, etc. is inside that properties box for that control and you change the value in the code.

Use two way binding to transfer changes from UI into database. Bind the checkboxes column to the Value field from SQL table. You will need a convertor for binding to transform from Yes/No into bool.
http://msdn.microsoft.com/en-us/magazine/cc163299.aspx#S3
http://msdn.microsoft.com/en-us/library/ms752347.aspx#data_conversion

Related

WPF Combobox will not send Selection Back to View Model [duplicate]

This question already has answers here:
DataGrid DataGridTemplateColumn ComboBox
(1 answer)
ComboBox SelectedItem property updating all other comboboxes in my Datagrid row
(1 answer)
Closed 2 years ago.
I have a WPF application that has a Combobox that is supposed to be bound to a boolean value. The UI should have a combobox with just two choices to choose from. Here is what I have so far. The XAML:
<DataGridTemplateColumn Header="Instance" Width="Auto">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate DataType="{x:Type dataModel:ParameterSetting}">
<Grid Visibility="{Binding IsPlaceholder, Converter={StaticResource BoolToVisInvert}}">
<ComboBox SelectedIndex="{Binding Instance, Mode=TwoWay, Converter={StaticResource ConvBoolToInstance}}">
<ComboBoxItem>Instance</ComboBoxItem>
<ComboBoxItem>Type</ComboBoxItem>
</ComboBox>
</Grid>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
The referenced converter:
[ValueConversion(typeof(bool), typeof(int))]
public class ConvBoolToInstance : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (DesignerProperties.GetIsInDesignMode(new DependencyObject())) return 0;
if (!(value is bool e))
throw new ArgumentException(#"Value was not a boolean and could not be converted", nameof(value));
return e ? 0 : 1;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (DesignerProperties.GetIsInDesignMode(new DependencyObject())) return true;
if (value == null || !(value is int i))
throw new ArgumentException(#"Value was not an integer and could not be converted", nameof(value));
return i == 0;
}
}
And the property that it's trying to bind to:
/// <summary>
/// If the parameter should be added as instance
/// </summary>
public bool Instance
{
get => _instance;
set
{
if (_instance == value) return;
_instance = value;
OnPropertyChanged(nameof(Instance));
}
}
When I debug this I get the correct choices in the combobox. I can change the default of the field and the combobox displays the correct item, plus I can set a breakpoint on the getter for the property and it's hit so I know that is correctly bound and going to the property I want it to. However, when I change the combobox value it changes the UI but doesn't push back to the property value on the object. I have set break points in both the property setter and the converter and neither are hit. From what I can tell it's just not pushing it back which is what it should do with a two way binding...
What am I missing?
EDIT
The converter is thanks to this answer but I have also tried biding to it as a SelectedValue with boolean combobox items but nothing seems to make it bind back...
EDIT
I should also mention this is inside a DataGrid. Updated question to show more of the XAML
Ok finally figured this out and a bit of a face palm, but posting the answer to help anyone in my same position. The answer was to use UpdateSourceTrigger=PropertyChanged. I believe it defaults to LostFocus which is fine but in this case it was REALLY delayed. Like I selected something in the ComboBox, then clicked into another cell to edit it, then clickout out of THAT cell which apparently finally took focus because THEN it committed. Not sure why it would be so delayed like that but once I switched to PropertyChanged it worked like a charm.
Here is my final binding (after figuring this out I was also able to just use normal binding without the converter):
SelectedItem="{Binding Instance, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"

WPF invokes value converter with empty string

I have a ComboBox bound to a list of values, for the sake of this example, a simple array of ints. The control has a custom ItemTemplate assigned to format its elements, which, in turn, uses an IValueConverter for some of its operation.
There's a particular case where this fails: If the ComboBox has an element selected, and the list of items changes, the converter's Convert is invoked with an empty string, which is most definitely not one of the values bound to my control. (Note that I'm not talking about the ConvertBack method.)
My questions would be:
Why is the IValueConverter being invoked with value being an empty string ("") when no string is ever bound to the control?
What are some non-hacky solutions to the problem? (I could just place if (value is "") return null; in the converter, and it seems to make the error go away, but I feel like it's treating the symptoms, not the cause.)
The problem can be reproduced with a simple WPF project (dotnet new wpf) containing only these 3 files (the problem is present on both the Framework and Core versions of .NET):
MainWindow.xaml:
<Window x:Class="test.MainWindow"
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"
xmlns:local="clr-namespace:test"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<ComboBox x:Name="Selector" VerticalAlignment="Center" HorizontalAlignment="Center" Width="100">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Converter={x:Static local:Converter.Instance}}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<Button HorizontalAlignment="Right" VerticalAlignment="Bottom" Content="Replace" Click="Button_Click" />
</Grid>
</Window>
MainWindow.xaml.cs:
using System;
using System.Windows;
namespace test
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Selector.ItemsSource = new int[] { 1, 2, 3 };
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Selector.ItemsSource = new int[] { -1, -2, -3 };
}
[STAThread]
public static void Main(String[] args)
{
new MainWindow().ShowDialog();
}
}
}
And finally Converter.cs:
using System;
using System.Diagnostics;
using System.Globalization;
using System.Windows.Data;
namespace test
{
class Converter : IValueConverter
{
public static Converter Instance { get; } = new Converter();
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
Debug.Assert(value is int);
return (2 * (int) value).ToString();
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
}
These 3 files form a minimal example that exhibits this behavior. If the "replace" button is clicked without selecting anything from the ComboBox first, the program runs fine. If, however, any value is selected in the ComboBox before clicking the button, the assertion in the converter fails, because upon clicking the button, the converter is passed a value of "".
I Tried your code when a currently selected item is not in the newly set item source the selected item should be changed right? So they change the selected item to "". That is the selected item you see in the initial state of the app running.
For a fact, if you keep the selected item in the new item source then it won't execute convert with value "".
Consider your initial item source is
Selector.ItemsSource = new int[] { 1, 2, 3 };
Now you select the second element which is displayed as 4 in your combo box and click replace to run this.
Selector.ItemsSource = new int[]{ -1, 2, -3 };
Then it won't execute the converter with value "".
Here the problem is the selected item is not present in the new item source so the Combobox is selecting its default value and your Combobox will behave like the exact way you started your application.

Is there any way to check for a condition in XAML

I have a Datagrid in which data comes from Database based on some selection and therefore the values keep on changing at different selections.
On the basis of the data, I want to add a TextBox to the UI?
This is .NET framework 4.5
<DataGrid Name="Sampledatagrid" AutoGenerateColumns="True" ItemsSource="`{StaticResource MyCustomers}" Margin="0,0,0,106"/>
<Canvas>
<br/>
<!-- if Sampledatagrid.Value == 'Adam' -->
<br/>
<br/>
<TextBox Canvas.Left="135" Canvas.Top="12" Style={StaticResource textboxstyle} />
<br/>
<br/>
</Canvas>
When the Sampledatagrid contains "Adam" it should display a textbox.
First, to let your TextBox show the selected entry of the DataGrid, set its Text-Binding to the corresponding value.
Just add the 'Text' property in the correct way:
<TextBox Text="{Binding ElementName=Sampledatagrid, Path=SelectedItem.Name}" Canvas.Left="135" Canvas.Top="12">
Possibly, the name of your variable "SelectedItem.Name" is another one than "Name".
Second, if the TextBox shall only show 'valid' names (like e.g. 'Adam'), I show you how to use a converter to do so.
Create a new file in your project called 'ValidNamesConverter.cs'. This file gets following code:
using System;
using System.Globalization;
using System.Windows.Data;
namespace WpfApp1
{
internal class ValidNamesConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
string valAsString = value.ToString();
if (valAsString == "Adam" || valAsString == "Eve")
return value;
return string.Empty;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
In the "Resources" section of your MainWindow.xaml (or UserControl.xaml) add an instance (a static resource) of this converter-class. (if you don't have already a "Resources" section, just add one):
<Window.Resources>
<!-- make a XAML instance of the class ValidNamesConverter -->
<local:ValidNamesConverter x:Key="validNamesConverter" />
</Window.Resources>
Then, extend the TextBox's Text-Binding to use this converter.
<TextBox Text="{Binding ElementName=Sampledatagrid, Path=SelectedItem.Name, Converter={StaticResource validNamesConverter}}" Canvas.Left="135" Canvas.Top="42">
The converter in this case decides, which string shall be 'forwarded' to the TextBox. So, if a valid name is given into the converter, it will just return that name again. If an invalid name is given, the converter returns an empty string.
Anyway, in my example, the TextBox is always visibly shown. If you want the TextBox to be absent when an invalid name is selected, you probably need a second converter (e.g. ValidNameToVisibilityConverter) which you bind to the TextBox's Visibility-property. That converter then returns either Visibility.Visible or Visibility.Collapsed. Within this 2nd converter you can make use of the ValidNamesConverter to avoid having a set of valid names twice in your code.

Why does the Value of the TextBox get reset to the previous value instead of showing an error?

I have a sample where I bind a view model's properties with some TextBox controls, including validation rules. In most cases, this works fine. But when I try to include the IsFocused property of the bound TextBox, I am having trouble in the case when an invalid number is entered in the control.
When I input the wrong number in the TextBox controls that are bound directly to the view model's property, the errors are shown as expected (red border around the TextBox). But in the TextBox that is bound with a MultiBinding that includes both the view model property and the IsFocused property of the TextBox, the error is not shown and the value gets reset to the previous valid value.
For example, if a number less than 10 is invalid, and I input 3, when the TextBox loses focus, a red border normally would appear in the TextBox signaling the error. But in the TextBox which includes IsFocused as a source for its binding, the value changes back to the previous valid value (if there was a 39 before I entered 3, the TextBox changes back to 39).
Using the code below you can reproduce the issue:
TestViewModel.cs
public class TestViewModel
{
public double? NullableValue { get; set; }
}
MainWindow.xaml
<Window x:Class="TestSO34204136TextBoxValidate.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:l="clr-namespace:TestSO34204136TextBoxValidate"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<l:TestViewModel/>
</Window.DataContext>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="Nullable: "/>
<TextBox VerticalAlignment="Top" Grid.Column="1">
<TextBox.Text>
<MultiBinding Mode="TwoWay">
<Binding Path="NullableValue"/>
<Binding Path="IsFocused"
RelativeSource="{RelativeSource Self}"
Mode="OneWay"/>
<MultiBinding.ValidationRules>
<l:ValidateIsBiggerThanTen/>
</MultiBinding.ValidationRules>
<MultiBinding.Converter>
<l:TestMultiBindingConverter/>
</MultiBinding.Converter>
</MultiBinding>
</TextBox.Text>
</TextBox>
<TextBox VerticalAlignment="Top" Grid.Column="2"/>
</Grid>
</Window>
TestMultiBindingConverter.cs
public class TestMultiBindingConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values[0] != null)
return values[0].ToString();
return DependencyProperty.UnsetValue;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
if (value != null)
{
double doubleValue;
var stringValue = value.ToString();
if (Double.TryParse(stringValue, out doubleValue))
{
object[] values = { doubleValue };
return values;
}
}
object[] values2 = { DependencyProperty.UnsetValue };
return values2;
}
}
ValidateIsBiggerThanTen.cs
public class ValidateIsBiggerThanTen : ValidationRule
{
private const string errorMessage = "The number must be bigger than 10";
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
var error = new ValidationResult(false, errorMessage);
if (value == null)
return new ValidationResult(true, null);
var stringValue = value.ToString();
double doubleValue;
if (!Double.TryParse(stringValue, out doubleValue))
return new ValidationResult(true, null);
if (doubleValue <= 10)
return error;
return new ValidationResult(true, null);
}
}
Why are the errors not showing for the TextBox in the above example?
The cause of the behavior you're seeing is specifically that you've bound the TextBox's IsFocused property in your MultiBinding. This directly has the effect of forcing an update of the target of the binding when the focus changes.
In the scenario where validation fails, there is a very brief moment when the validation rule has fired, the error is set, but the focus hasn't actually been changed yet. But this all happens too fast for a user to see. And since validation failed, the source of the binding is not updated.
So when the IsFocused property value changes, after the validation and rejection of the entered value happens, the next thing to happen is that the binding is re-evaluated (because one of the source properties changed!) to update the target. And since the actual source value never changed, the target (the TextBox) reverts from whatever you typed back to whatever was stored in the source.
How should you fix this? It depends on the exact behavior desired. You have three basic options:
Keep binding to IsFocused, and add UpdateSourceTrigger="PropertyChanged". This will keep the basic current behavior of copying the old value back when focus is lost, but will at least provide the user with immediate validation feedback as the value is edited.
Remove binding to IsFocused altogether. Then the target of the binding won't depend on that, and won't be re-evaluated when focus changes. Problem solved. :)
Keep binding to IsFocused, and add logic so that the interaction with validation does not result in copying a stale value back to the TextBox.
Based on our comments back and forth, it seems that the third option above is the preferred one for your scenario, as you desire to format the text representation of the value differently when the control has focus vs. when it does not.
I am skeptical of the wisdom of a user interface that formats data differently depending on whether the control is focused or not. Of course, it makes complete sense for focus changes to affect the overall visual presentation, but that would generally involve things like underlining, highlighting, etc. Displaying a completely different string depending on whether the control is focused seems likely to interfere with user comprehension and possibly annoy them as well.
But I'm in agreement that this is a subjective point, and clearly in your case you have this specific behavior that is desirable for your specification and needs to be supported. So with that in mind, let's look at how you can accomplish that behavior…
If you want to be able to bind to the IsFocused property, but not have changes to focus copy over the current contents of the control if the source has not actually been updated yet (i.e. if a validation error prevented that from happening), then you can also bind to the Validation.HasError property, and use that to control the converter's behavior. For example:
class TestMultiBindingConverter : IMultiValueConverter
{
private bool _hadError;
public object Convert(object[] values,
Type targetType, object parameter, CultureInfo culture)
{
bool? isFocused = values[1] as bool?,
hasError = values[2] as bool?;
if ((hasError == true) || _hadError)
{
_hadError = true;
return Binding.DoNothing;
}
if (values[0] != null)
{
return values[0].ToString() + (isFocused == true ? "" : " (+)");
}
return DependencyProperty.UnsetValue;
}
public object[] ConvertBack(object value,
Type[] targetTypes, object parameter, CultureInfo culture)
{
if (value != null)
{
double doubleValue;
var stringValue = value.ToString();
if (Double.TryParse(stringValue, out doubleValue))
{
object[] values = { doubleValue };
_hadError = false;
return values;
}
}
object[] values2 = { DependencyProperty.UnsetValue };
return values2;
}
}
The above adds a field _hadError that "remembers" what's happened recently to the control. If the converter is called while validation is detecting an error, the converter returns Binding.DoNothing (which has the effect its name suggests :) ), and sets the flag. Thereafter, no matter what happens, as long as that flag is set the converter will always do nothing.
The only way that the flag will get cleared is if the user eventually enters text that is valid. Then the converter's ConvertBack() method will be called to update the source, and in doing so it can clear the _hadError flag. This ensures that the control contents will never get overwritten due to binding updates, except when there has been no error since the last time the source was updated.
Here's the XAML example above updated to use the additional binding input:
<Window x:Class="TestSO34204136TextBoxValidate.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:l="clr-namespace:TestSO34204136TextBoxValidate"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<l:TestViewModel/>
</Window.DataContext>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock Text="Nulleable: "/>
<TextBox x:Name="textBoxWrapper" Grid.Column="1" VerticalAlignment="Top">
<TextBox.Text>
<MultiBinding x:Name="TextBoxBinding" Mode="TwoWay"
UpdateSourceTrigger="PropertyChanged">
<Binding Path="NulleableValue"/>
<Binding Path="IsFocused"
RelativeSource="{RelativeSource Self}"
Mode="OneWay"/>
<Binding Path="(Validation.HasError)"
RelativeSource="{RelativeSource Self}"
Mode="OneWay"/>
<MultiBinding.ValidationRules>
<l:ValidateIsBiggerThanTen/>
</MultiBinding.ValidationRules>
<MultiBinding.Converter>
<l:TestMultiBindingConverter/>
</MultiBinding.Converter>
</MultiBinding>
</TextBox.Text>
</TextBox>
<TextBox VerticalAlignment="Top" Grid.Column="2"/>
</Grid>
</Window>
I should point out, in case it's not obvious: the _hadError field is for the converter itself. For the above to work correctly, you'll need a separate instance of the converter for each binding to which it's applied. There are alternative ways to track such a flag for each control uniquely, but I feel an extended discussion of the options in that respect are outside the scope of this question. Feel free to explore on your own, and post a new question regarding that aspect if you are unable to address the issue adequately on your own.

Use WPF styles like themes

I am now creating an application using WPF. Now I want to change the appearance of the application depend on the user input. Its mean that through a configuration window users can decide how the application looks like and depend on the selection it should change the styles. How can I achieve that rather use several styles per configuration.
For example-
Following rectangle consists of several texts. When restart the application, depend on the user selection it should display the content (changes saved in a some where and it can be easily get the current configuration details and depend on the saved details it should draw the appearance using WPF)
IF user select some option to display all 4 text it should display like in first image
If User select some option to to display only 3 or 2 texts, depend on the inner context it will re-size the rectangle(image 3/4).
For instance if this rectangle contain image it should re-size the rectangle accordingly. If user change the settings to remove the picture from the rectangle it should remove it and re-size the rectangle accordingly(image 4)
Place the texts (TextBox) and the image (Image) in a Grid to create the desired layout. The resizing will take place automatically.
Then, bind the Visibility property of each of your texts and your image to a property of some object that stores which state is selected in the options. (The best solution is to store this information in some new class of your own and assign an instance of that class to the DataContext property of your window.
For each of the bindings, create a value converter that returns either Visibility.Visible or Visibility.Collapsed, based on whether the respective element should be visible or invisible with the current options.
EDIT: Here is some exemplary code:
Assuming your very simple settings object looks like this:
public enum GuiMode {
FourTexts,
ThreeTexts,
OneText,
ThreeTextsAndImage
}
public class GuiSettings : INotifyPropertyChanged
{
public PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null) {
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
private GuiMode mode = GuiMode.FourTexts;
public GuiMode Mode {
get {
return mode;
}
set {
if (mode != value) {
switch (value) {
case GuiMode.FourTexts:
case GuiMode.ThreeTexts:
case GuiMode.OneText:
case GuiMode.ThreeTextsAndImage:
mode = value;
OnPropertyChanged("Mode");
break;
default:
throw new InvalidEnumArgumentException("value", (int)value, typeof(GuiMode));
}
}
}
}
}
This stores the mode of your GUI. Note the implementation of INotifyPropertyChanged, so when binding to the Mode property, changes of the Mode property will automatically update anything bound to it.
Then, for example, for text2, you could write the following value converter:
public class Text2VisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
switch ((GuiMode)value) {
case GuiMode.OneText:
return Visibility.Collapsed;
default:
return Visibility.Visible;
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotSupportedException("This converter does not convert back.");
}
}
As text2 is always visible, except for the state when there is only one text displayed - GuiMode.OneText -, the respective Visibility values are returned by the converter. Also note that this converter simply assumes that the incoming value is a GuiMode value. To do this properly, you should check both what you are getting in value, as well as the targetType.
Once this is done, you can import the converter as a static resource into your Xaml:
<Window.Resources>
<Text2VisibilityConverter x:Key="text2vis"/>
</Window.Resources>
Depending on which namespaces you have imported, you might need to add the appropriate namespace prefix in front of Text2VisibilityConverter there.
The Visibility property of your text2 can then be bound to the Mode property from the GuiSettings class by using the Text2VisibilityConverter, assuming that the GuiSettings instance where you store your settings has been assigned to the DataContext property of the window:
<TextBlock Text="Text 2" Visibility="{Binding Mode, Converter={StaticResource text2vis}}"/>
Once that works, you can add more value converter classes for the visibilities of the other controls.
The question is pretty general so I'll refer you to a general how on using styles and templates to control how your WPF controls look.
http://msdn.microsoft.com/en-us/magazine/cc163497.aspx
There are several way you can change how your controls look and act at run time.
A direct and easy to understand way(if you've come from winforms) to interact wpf templates is is by overriding the OnApplyTemplate method and then setting the template you want to use from a library of templates you've created or procured.
http://msdn.microsoft.com/en-us/library/system.windows.frameworkelement.onapplytemplate.aspx
But what the best approach for you really depends on how you are loading your users preferences and the fundamental design of your UI, MVVM vs MVC vs Custom Controls, etc.
You can try something similar to this:
<Grid>
<StackPanel Orientation="Horizontal" VerticalAlignment="Bottom" Height="30">
<Button Content="Option1" Name="Option1" Click="Option1_OnClick"></Button>
<Button Content="Option2" Name="Option2" Click="Option2_OnClick"></Button>
<Button Content="Option3" Name="Option3" Click="Option3_OnClick"></Button>
<Button Content="Full" Name="Full" Click="Full_OnClick"></Button>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Image Source="/WpfApplication3;component/Resources/vaca.png" HorizontalAlignment="Left" VerticalAlignment="Top" Width="150" Height="150" Name="Image"></Image>
<StackPanel Orientation="Vertical" >
<Label Content="Text1" Name="Text1" />
<Label Content="Text2" Name="Text2" />
<Label Content="Text3" Name="Text3" />
<Label Content="Text4" Name="Text4" />
</StackPanel>
</StackPanel>
</Grid>
Code behind:
private void Option1_OnClick(object sender, RoutedEventArgs e)
{
Image.Visibility = Visibility.Collapsed;
}
private void Option2_OnClick(object sender, RoutedEventArgs e)
{
Image.Visibility = Visibility.Collapsed;
Text4.Visibility = Visibility.Collapsed;
}
private void Option3_OnClick(object sender, RoutedEventArgs e)
{
Image.Visibility = Visibility.Collapsed;
Text4.Visibility = Visibility.Collapsed;
Text3.Visibility = Visibility.Collapsed;
Text2.Visibility = Visibility.Collapsed;
}
private void Full_OnClick(object sender, RoutedEventArgs e)
{
Image.Visibility = Visibility.Visible;
Text4.Visibility = Visibility.Visible;
Text3.Visibility = Visibility.Visible;
Text2.Visibility = Visibility.Visible;
}

Categories