I have 5 CheckBox and this is what they look like in the View:
<CheckBox IsChecked="{Binding Path=IsSelected, Mode=TwoWay}" Content="Cb1"/>
<CheckBox IsChecked="{Binding Path=IsSelected, Mode=TwoWay}" Content="Cb2"/>
<CheckBox IsChecked="{Binding Path=IsSelected, Mode=TwoWay}" Content="Cb3"/>
<CheckBox IsChecked="{Binding Path=IsSelected, Mode=TwoWay}" Content="Cb4"/>
<CheckBox IsChecked="{Binding Path=IsSelected, Mode=TwoWay}" Content="Cb5"/>
This is the some of the code that I have in my ViewModel:
class CheckBoxesViewModel : INotifyPropertyChanged
{
public CheckBoxesViewModel()
{
CheckBoxes= new ObservableCollection<Models.CheckBoxes>();
_canExecute = true;
}
private bool _IsSelected;
public bool IsSelected
{
get
{
return _IsSelected;
}
set
{
_IsSelected = value;
OnPropertyChanged("IsSelected");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
private ObservableCollection<Models.CheckBoxes> _checkBoxes = new ObservableCollection<Models.CheckBoxes>();
public ObservableCollection<Models.CheckBoxes> CheckBoxes
{
get { return _checkBoxes ; }
set
{
_checkBoxes = value;
OnPropertyChanged("CheckBoxes");
}
}
}
The problem is that when I check/uncheck one of the checkboxes it affects all of them.
I assume that is because they have exact same binding, but I can not figure out how to make the code distinguish them.
I think I could use Command and CommandParameters, but that does not seem like the best solution.
P.S. Do let me know if you see something wrong with my code - I am still trying to learn the whole MVVM thing.
You need to implement ICommand (google DelegateCommand to be able to treat an Action as ICommand) then you would bind the Command property of the CheckBox in the view to the Command on the view model.
ViewModel
public ICommand MyCommand { get; private set; }
.... MyCommand = new DelegateCommand((value) => this.DoStuff(value));
Xaml
<CheckBox Command={Binding MyCommand} Command Parameter={...} />
From your stated purpose in comments (which really should have been in your question--this is a classic XY problem)
You're attempting to route View logic through your ViewModel, which should be a hint that something's wrong here. Your stated purpose is
Each CheckBox has a corresponding TextBox that gets shown when it is checked. I was hoping to reuse the same code for all of the CheckBoxes and only change some value that helps me distinguish them (e.g. Content)
Toggling visibility is a View concern. You can do it thusly
<StackPanel>
<CheckBox x:Name = "cb1" />
<!-- cb2 through cbn omitted -->
<StackPanel />
<StackPanel>
<StackPanel.Resources>
<BooleanToVisibilityConverter x:Key="btvc" />
</StackPanel.Resources>
<TextBox Text="{Binding FirstTextBox}"
Visibility="{Binding IsChecked,
ElementName=cb1,
Converter={StaticResource btvc}}" />
<!-- SecondTextBox through NthTextBox omitted -->
</StackPanel />
I'm toggling visibility of the textbox by whether or not the corresponding checkbox was checked.
Now, if you're trying to munge together N textbox values into one property... You're making life too hard on yourself.
If you wish to 'programmatically add them", then you need to reverse your logic. Instead of 'adding controls' to the form, you need to think of 'adding data' to your ViewModel. This is how you stay within MVVM guidelines, as your tag suggests.
Here's how you can reverse the logic....The ItemsControl has the ability to bind to a collection of ViewModels. This control also 'automagically' determines what control to use for each item in the collection by using DataTemplates.
Here's the XAML code:
<ItemsControl ItemsSource="{Binding myCollection}" >
<ItemsControl.Resources>
<DataTemplate DataType="{x:Type local:myViewModelForItemA}">
<CheckBox IsChecked="{Binding IsChecked}" Content="{Binding aName}"></CheckBox>
</DataTemplate>
<DataTemplate DataType="{x:Type local:myViewModelForItemB}">
<RadioButton IsChecked="{Binding IsChecked}" Content="{Binding aName}"></RadioButton>
</DataTemplate>
</ItemsControl.Resources>
</ItemsControl>
As you can probably see, the Binding "myCollection" is the collection you add your ViewModel Instances to (this is an ObservableCollection).
Each DataTemplate in the IntemsControl.Resources is how you want each item to look (you can even place multiple controls inside each DataTemplate, just remember that whatever you bind these to will bind to the ViewModel in the collection (i.e. myViewModelForItemA, myViewModelForItemB).
The code in your main view model:
public ObservableCollection<object> myCollection { set; get; }
....
myCollection = new ObservableCollection<object>();
myViewModelForItemA anItem = new myViewModelForItemA();
myCollection.Add(anItem);
//now anItem of type (myViewModelForItemA) is in our collection
//and the ItemsControl automagically added a CheckBox to it's collection
//and bound isChecked to anItem.isChecked property, and bound
//the Content to anItem.aName property.
Related
FirstView.xaml contains Something like this
<ContentControl Name="ContentControlName" Grid.Row="1" Grid.Column="0" Content="{Binding SelectionViewModel}"/>
My SelectionView.xaml contains
<TextBox x:Name="textBoxName" Text="{Binding Name}"/>
<TextBox IsReadOnly="True" Text="{Binding Uid}"/>
In the FirstViewModel I have created a property like below
private SelectionViewModel selectionViewModel;
public SelectionViewModel SelectionViewModel
{
get
{
return this.selectionViewModel;
}
}
Content control with two text box is not displayed when I run
Is the way done right?
Since you used binding, you need raise up PropertyChanged event.
Your ViewModel class (SelectionViewModel) must implement INotifyPropertyChanged.
public class MainViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private SelectionViewModel selectionViewModel;
public SelectionViewModel SelectionViewModel
{
get
{
return this.selectionViewModel;
}
private set
{
this.selectionViewModel = value;
PropertyChanged?.Invoke(this, nameof(SelectionViewModel));
}
}
}
You passed SelectionViewModel instance to Content property of ContentControl.
Your ContentControl must have special datatemplate coupled with this view model. Otherwise, it will not work.
For example:
<ContentControl Content="{Binding SelectionViewModel}">
<ContentControl.ContentTemplate>
<DataTemplate DataType="{x:Type local:SelectionViewModel}">
<!-- Here is your template -->
</DataTemplate>
</ContentControl.ContentTemplate>
</ContentControl>
Also you shouldn't use same names for type SelectionViewModel and property SelectionViewModel.
Since you wasn't provide a source code we can't figure out the exact cause of your error.
I hope it was helpful for you.
I have some XAML that looks (trimmed) like this, with a button tying its IsEnabled attribute to a subproperty:
<Grid DataContext="{Binding RelativeSource={RelativeSource AncestorType=Window}}">
...
<Button x:Name="continueButton" Content="Continue" IsEnabled="{Binding CurrentQuestion.AnswerSelected, Mode=OneWay}" Click="continueButton_Click"/>
...
CurrentQuestion is a property that pulls the current one from a collection:
public Question CurrentQuestion {
get
{
return Questions[QuestionNo];
}
set
{
Questions[QuestionNo] = value;
}
}
AnswerSelected checks whether any of the Answers are marked as selected.
public bool AnswerSelected
{
get
{
return Answers.Any(a => a.Selected);
}
}
The Selected property itself is set by radio buttons bound to the possible answers. Thus, the user should be able to continue after choosing an answer.
The Answers collection is monitored for changes, and calls the OnPropertyChanged() method from INotifyPropertyChanged for the AnswerSelected bool property like so:
public Answer[] Answers
{
get
{
return _answers;
}
set
{
_answers = value;
OnPropertyChanged("Answers");
OnPropertyChanged("AnswerSelected");
}
}
The binding successfully sets the button to disabled to begin with, but no change to the radio buttons then re-enables the button. I tried moving AnswerSelected to be a property at the same level as CurrentQuestion but this didn't work either.
What am I missing to get this button to re-enable? Also, is there a better way to accomplish this same thing?
Edit:
This is the code for the radio button setting.
<Grid DataContext="{Binding CurrentQuestion, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}">
<ItemsControl ItemsSource="{Binding Answers}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<RadioButton GroupName="AnswerGroup" IsChecked="{Binding Selected}">
<TextBlock Text="{Binding Text}" />
</RadioButton>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
So it looks like this:
CurrentAnswer (Questions[QuestionNo])
AnswerSelected (Answers.Any(a => a.Selected))
Edit 2:
I think my question, effectively, is this: The bound property is a calculated property, but the calculation uses the subproperty of an array element. How do I, therefore, raise notification when that subproperty is changed, which itself is in a different class that defines each array element?
What I eventually needed to do, in a way that was influenced by this question, was to subscribe to the PropertyChanged event of each Answer from the Question class.
void SubscribeToSelect(Answer item)
{
item.PropertyChanged += (s, e) => this.AnswerSelected = e.PropertyName == "Selected" && item.Selected ? true : this.AnswerSelected;
}
When that fired, I updated the Question.AnswerSelected property and fired an update on that too, which in turn updated the binding to the button:
private bool _answerSelected;
public bool AnswerSelected
{
get
{
return _answerSelected;
}
set
{
_answerSelected = value;
OnPropertyChanged("AnswerSelected");
}
}
I have a ComboBox with its ItemsSource set to an IList of MyClass objects. I overrode the ComboBox's ItemTemplate to display a CheckBox next to the items. I want to have an item at the top that says "Select All" and when the user checks that CheckBox, the code checks all CheckBoxes. My question is, what is the MVVM way of doing this?
I don't want to add a separate MyClass object to the IList. That seems like it would involve too much coupling of the view and the model. Is there a way to add an item directly in the XAML code and give it a Command that checks all of the Checkboxes?
My ComboBox XAML right now is:
<ComboBox ItemsSource="{Binding MyList}" Width="200">
<ComboBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Name}" IsChecked="{Binding Selected}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
That looks like:
I'd like it to look like:
My MyClass is simply this:
public class MyClass
{
public string Name { get; set; }
public bool Selected { get; set; }
}
Edit: I found a way to add an item to the collection in the XAML code using the example here. I would still need a way run code when the user checks the checkbox for that "Select All" item. To just add the item, the code is this:
<ComboBox Width="200">
<ComboBox.Resources>
<CollectionViewSource x:Key="comboBoxSource" Source="{Binding Path=MyList}" />
</ComboBox.Resources>
<ComboBox.ItemsSource>
<CompositeCollection>
<local:MyClass Name="Select All" Selected="False">
</local:MyClass>
<CollectionContainer Collection="{Binding Source={StaticResource comboBoxSource}}" />
</CompositeCollection>
</ComboBox.ItemsSource>
<ComboBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Name}" IsChecked="{Binding Selected}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Id personally just modify the CheckBox's Template and add custom CheckBox there with Click handler, nothing too fancy, easy to understand.
http://msdn.microsoft.com/en-us/library/ms752094(v=vs.110).aspx
From there you can modify this part:
<ScrollViewer Margin="4,6,4,6"
SnapsToDevicePixels="True">
<StackPanel IsItemsHost="True"
KeyboardNavigation.DirectionalNavigation="Contained" />
</ScrollViewer>
The other way I would model is this simply as to create
public class MyClassViewModel
{
public string Name { get; set; }
public bool Selected { get; set; }
public ICommand Execute {get; set;}
}
and add custom object to your IList. This will work nicely, without any crap, your viewmodel has no idea about view, + it's testable. win-win for everyone.
Whenever your Button to select all is pressed you can invoke action, binding to itemssource, enumerating throughout collection setting Selected value to true. This solutiond requires Blend interface.
<local:MyClass Name="Select All" Selected="False">
<i:Interaction.Triggers>
<ic:DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Selected}" Value="True">
<local:SelectAll TargetObject="{Binding RelativeSource={RelativeSource AncestorType=ComboBox}, Path=ItemsSource}"/>
</ic:DataTrigger>
</i:Interaction.Triggers>
</local:MyClass>
and then create class SelectAll as follows
public class SelectAll : TargetedTriggerAction<List<MyClass>>
{
protected override void Invoke(object parameter)
{
if (Target is List<MyClass>)
foreach (var elem in (List<MyClass>)Target)
elem.Selected = true;
}
}
You have to registed the event when selecting a item, and when selecting the item,check that the item selected is the first one(using index) and then,change the selection to what do you need.
(Dont have the IDE here,sorry for not code).
I figured out a way to do it that uses some simpler concepts.
My first problem was that I wanted to add a "Select All" item to the top of the list without actually adding an item to the databound IList<MyClass>. I edited my original post to show that I can use a CompositeCollection to do this. I made the "Select All" databound object a subclass of MyClass and called the class MyClassSelectAll. More on this below.
My second problem was that I needed to handle the CheckBox.Click event differently for the "Select All" item than for the regular MyClass items. I gave each CheckBox a Command that I can use to check the CheckBoxes. To do this, I need a reference to both the IList<MyClass> and the CheckBox on which the user clicked (more specfically the MyClass object databound to that CheckBox).
I found one way to solve my second problem is to set the CheckBox.CommandParameter to a MultiBinding that contains those two objects. In the Command.Execute(object) method, I can easily check if the current MyClass is a MyClassSelectAll, and if so, I can loop through the IList<MyClass> list (which doesn't contain the "Select All" item) and set the "Selected" property appropriately.
Here's my relevant XAML code:
<Grid.Resources>
<local:MyCommand x:Key="kMyCommand" />
<local:MyConverter x:Key="kConv" />
</Grid.Resources>
<ComboBox Width="200">
<ComboBox.Resources>
<CollectionViewSource x:Key="comboBoxSource" Source="{Binding Path=MyList}" />
</ComboBox.Resources>
<ComboBox.ItemsSource>
<CompositeCollection>
<local:MyClassSelectAll Name="Select All" Selected="False" />
<CollectionContainer Collection="{Binding
Source={StaticResource comboBoxSource}}" />
</CompositeCollection>
</ComboBox.ItemsSource>
<ComboBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Name}"
IsChecked="{Binding Selected}"
Command="{StaticResource kMyCommand}">
<CheckBox.CommandParameter>
<MultiBinding Converter="{StaticResource kConv}">
<Binding RelativeSource="{RelativeSource
FindAncestor, AncestorType={x:Type Window}}"
Path="DataContext.MyList" />
<Binding Path="." />
</MultiBinding>
</CheckBox.CommandParameter>
</CheckBox>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
I updated MyClass to implement INotifyPropertyChanged appropriately. The code is simple, so I won't post it here.
MyConverter is pretty simple as well; it just packages the list and current item object into a MyCommandArgs object:
class MyConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType,
object parameter, System.Globalization.CultureInfo culture)
{
MyCommandArgs result = new MyCommandArgs()
{
MyList = values[0] as IList<MyClass>,
CurrentItem = values[1] as MyClass
};
return result;
}
public object[] ConvertBack(object value, Type[] targetTypes,
object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
The MyCommandArgs class that I use to pass around the MyList and CurrentItem references is a simple container class so I won't post it here.
MyClassSelectAll is the simplest; its only job is to flag the "Select All" MyClass object as something that selects all.
class MyClassSelectAll : MyClass
{
}
Finally, The MyCommand object that handles the click event.
class MyCommand : ICommand
{
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
var mylist = parameter as MyCommandArgs;
if (mylist != null && mylist.CurrentItem is MyClassSelectAll)
{
foreach (var item in mylist.MyList)
{
item.Selected = mylist.CurrentItem.Selected;
}
}
}
}
Thanks everyone. I was really stuck on this. It seems like many times when I have a problem doing something in WPF, the solution is to use a Converter.
I have MVVM master /details like this:
<Window.Resources>
<DataTemplate DataType="{x:Type model:EveryDay}">
<views:EveryDayView/>
</DataTemplate>
<DataTemplate DataType="{x:Type model:EveryMonth}">
<views:EveryMonthView/>
</DataTemplate>
</Window.Resources>
<Grid>
<ListBox Margin="12,24,0,35" Name="schedules"
IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding Path=Elements}"
SelectedItem="{Binding Path=CurrentElement}"
DisplayMemberPath="Name" HorizontalAlignment="Left" Width="120"/>
<ContentControl Margin="168,86,32,35" Name="contentControl1"
Content="{Binding Path=CurrentElement.Schedule}" />
<ComboBox Height="23" Margin="188,24,51,0" Name="comboBox1"
VerticalAlignment="Top"
IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding Path=Schedules}"
SelectedItem="{Binding Path=CurrentElement.Schedule}"
DisplayMemberPath="Name"
SelectedValuePath="ID"
SelectedValue="{Binding Path=CurrentElement.Schedule.ID}"/>
</Grid>
This Window has DataContext class:
public class MainViewModel : INotifyPropertyChanged {
public MainViewModel() {
elements.Add(new Element("first", new EveryDay("First EveryDay object")));
elements.Add(new Element("second", new EveryMonth("Every Month object")));
elements.Add(new Element("third", new EveryDay("Second EveryDay object")));
schedules.Add(new EveryDay());
schedules.Add(new EveryMonth());
}
private ObservableCollection<ScheduleBase> _schedules = new
ObservableCollection<ScheduleBase>();
public ObservableCollection<ScheduleBase> Schedules {
get {
return _schedules;
}
set {
schedules = value;
this.OnPropertyChanged("Schedules");
}
}
private Element _currentElement = null;
public Element CurrentElement {
get {
return this._currentElement;
}
set {
this._currentElement = value;
this.OnPropertyChanged("CurrentElement");
}
}
private ObservableCollection<Element> _elements = new
ObservableCollection<Element>();
public ObservableCollection<Element> Elements {
get {
return _elements;
}
set {
elements = value;
this.OnPropertyChanged("Elements");
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName) {
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) {
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
}
One of Views:
<UserControl x:Class="Views.EveryDayView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid >
<GroupBox Header="Every Day Data" Name="groupBox1" VerticalAlignment="Top">
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<TextBox Name="textBox2" Text="{Binding Path=AnyDayData}" />
</Grid>
</GroupBox>
</Grid>
My SelectedItem in ComboBox doesn't works correctly. Are there any visible errors in my code?
What I usually do is bind the items of an ItemsControl to an ICollectionView (usually ListCollectionView) instead of directly to a collection; I think that's what the ItemsControl does by default anyway (creates a default ICollectionView), but I might be wrong.
Anyway, this allows you to work with the CurrentItem property of the ICollectionView, which is automatically synchronized with the selected item in an ItemsControl (if the IsSynchronizedWithCurrentItem property of the control is true or null/default). Then, when you need the current item in the ViewModel, you can use that instead. You can also set the selected item by using the MoveCurrentTo... methods on the ICollectionView.
But as I re-read the question I realize you may have another problem altogether; you have a collection of 'default' items and need a way to match them to specific instances. It would however be a bad idea to override the equality operators of the objects to consider them always equal if they are of the same type, since that has the potential to make other code very confusing. I would consider extracting the type information into an enum, and put a read-only property on each object returning one of the enum values. Then you can bind the items to a collection of the enum values, and the selected item to the enum property of each object.
Let me know if you need an example, I may have made a mess of the explanation :)
While it is trivial to store a checkbox's checked state in a variable using the checkbox's Click event, how would I do it via databinding? All the examples I have found have the UI updated from some datasource, or bind one control to another; I want to update a member variable when the checkbox is clicked.
TIA for any pointers...
You must make your binding bidirectional :
<checkbox IsChecked="{Binding Path=MyProperty, Mode=TwoWay}"/>
You need a dependency property for this:
public BindingList<User> Users
{
get { return (BindingList<User>)GetValue(UsersProperty); }
set { SetValue(UsersProperty, value); }
}
public static readonly DependencyProperty UsersProperty =
DependencyProperty.Register("Users", typeof(BindingList<User>),
typeof(OptionsDialog));
Once that is done, you bind the checkbox to the dependency property:
<CheckBox x:Name="myCheckBox"
IsChecked="{Binding ElementName=window1, Path=CheckBoxIsChecked}" />
For that to work you have to name your Window or UserControl in its openning tag, and use that name in the ElementName parameter.
With this code, whenever you change the property on the code side, you will change the textbox. Also, whenever you check/uncheck the textbox, the Dependency Property will change too.
EDIT:
An easy way to create a dependency property is typing the snippet propdp, which will give you the general code for Dependency Properties.
All the code:
XAML:
<Window x:Class="StackOverflowTests.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" x:Name="window1" Height="300" Width="300">
<Grid>
<StackPanel Orientation="Vertical">
<CheckBox Margin="10"
x:Name="myCheckBox"
IsChecked="{Binding ElementName=window1, Path=IsCheckBoxChecked}">
Bound CheckBox
</CheckBox>
<Label Content="{Binding ElementName=window1, Path=IsCheckBoxChecked}"
ContentStringFormat="Is checkbox checked? {0}" />
</StackPanel>
</Grid>
</Window>
C#:
using System.Windows;
namespace StackOverflowTests
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
public bool IsCheckBoxChecked
{
get { return (bool)GetValue(IsCheckBoxCheckedProperty); }
set { SetValue(IsCheckBoxCheckedProperty, value); }
}
// Using a DependencyProperty as the backing store for
//IsCheckBoxChecked. This enables animation, styling, binding, etc...
public static readonly DependencyProperty IsCheckBoxCheckedProperty =
DependencyProperty.Register("IsCheckBoxChecked", typeof(bool),
typeof(Window1), new UIPropertyMetadata(false));
public Window1()
{
InitializeComponent();
}
}
}
Notice how the only code behind is the Dependency Property. Both the label and the checkbox are bound to it. If the checkbox changes, the label changes too.
Hello this is my first time posting so please be patient:
my answer was to create a simple property:
public bool Checked { get; set; }
Then to set the data context of the Checkbox (called cb1):
cb1.DataContext = this;
Then to bind the IsChecked proerty of it in the xaml
IsChecked="{Binding Checked}"
The code is like this:
XAML
<CheckBox x:Name="cb1"
HorizontalAlignment="Left"
Margin="439,81,0,0"
VerticalAlignment="Top"
Height="35" Width="96"
IsChecked="{Binding Checked}"/>
Code behind
public partial class MainWindow : Window
{
public bool Checked { get; set; }
public MainWindow()
{
InitializeComponent();
cb1.DataContext = this;
}
private void myyButton_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show(Checked.ToString());
}
}
Should be easier than that. Just use:
<Checkbox IsChecked="{Binding Path=myVar, UpdateSourceTrigger=PropertyChanged}" />
if you have the property "MyProperty" on your data-class, then you bind the IsChecked like this.... (the converter is optional, but sometimes you need that)
<Window.Resources>
<local:MyBoolConverter x:Key="MyBoolConverterKey"/>
</Window.Resources>
<checkbox IsChecked="{Binding Path=MyProperty, Converter={StaticResource MyBoolConverterKey}}"/>
This works for me (essential code only included, fill more for your needs):
In XAML a user control is defined:
<UserControl x:Class="Mockup.TestTab" ......>
<!-- a checkbox somewhere within the control -->
<!-- IsChecked is bound to Property C1 of the DataContext -->
<CheckBox Content="CheckBox 1" IsChecked="{Binding C1, Mode=TwoWay}" />
</UserControl>
In code behind for UserControl
public partial class TestTab : UserControl
{
public TestTab()
{
InitializeComponent(); // the standard bit
// then we set the DataContex of TestTab Control to a MyViewModel object
// this MyViewModel object becomes the DataContext for all controls
// within TestTab ... including our CheckBox
DataContext = new MyViewModel(....);
}
}
Somewhere in solution class MyViewModel is defined
public class MyViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private bool m_c1 = true;
public bool C1 {
get { return m_c1; }
set {
if (m_c1 != value) {
m_c1 = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("C1"));
}
}
}
}
No backend and ViewModel Code:
I made such check box to control other control's visibility.
<CheckBox x:Name="rulerCheckbox" Content="Is Ruler Visible" IsChecked="True"/>
and in the other control, I added such binding:
Visibility="{Binding IsChecked, ElementName=rulerCheckbox, Mode=TwoWay, Converter={StaticResource BoolVisConverter}}">