Bind value in checkbox silverlight - c#

I have 3 Checkbox in xaml file.Name sit,stand,sleep.
Extype having the following values 1,2,3
CheckBox Content="Sit" Margin="127,89,212,136" IsChecked="{Binding Extype}" RenderTransformOrigin="1.817,-1.029"/>
CheckBox Content="Stand" Margin="127,89,212,136" IsChecked="{Binding Extype}" RenderTransformOrigin="1.817,-1.029"/>
CheckBox Content="Sleep" Margin="127,89,212,136" IsChecked="{Binding Extype}" RenderTransformOrigin="1.817,-1.029"/>
If the Extype value is one means I need to select Sit check box.
If the Extype value is two means I need to select stand check box.
If the Extype value is three means I need to select both check boxes.
How can I do this?

XAML:
<CheckBox Content="Sit" IsChecked="{Binding IsSit, Mode=OneWay}" IsEnabled="False"/>
<CheckBox Content="Stand" IsChecked="{Binding IsStand, Mode=OneWay}" IsEnabled="False"/>
<CheckBox Content="Sleep" IsChecked="{Binding IsSleep, Mode=OneWay}" IsEnabled="False"/>
ViewModel:
public bool IsSit
{
get
{
return ExtType == 1 || ExtType == 3;
}
}
public bool IsStand
{
get
{
return ExtType == 2 || ExtType == 3;
}
}
private int _extType;
public int ExtType
{
get
{
return _extType;
}
set
{
_extType = value;
RaisePropertyChanged("IsSit");
RaisePropertyChanged("IsStand");
}
}

You can use a ValueConverter with a parameter. Use the same ValueConverter in each checkbox but change the parameter value.
<CheckBox Content="Sit" IsChecked="{Binding Extype, Converter={StaticResource YourConverter}, ConverterParameter=Sit}" />
<CheckBox Content="Standup" IsChecked="{Binding Extype, Converter={StaticResource YourConverter}, ConverterParameter=Standup}" />
Here an example of a ValueConverter with parameters:
http://wpftutorial.net/ValueConverters.html
(Remember to add your ValueConverter as a Resource.)
And then put your business logic code inside the ValueConverter or even better, call a function in your Business Layer.

Related

Bind IsEnabled property to Boolean in WPF

I have a TextBox which needs to be enabled / disabled programmatically. I want to achieve this using a binding to a Boolean. Here is the TextBox XAML:
<TextBox Height="424" HorizontalAlignment="Left"
Margin="179,57,0,0" Name="textBox2"
VerticalAlignment="Top" Width="777"
TextWrapping="WrapWithOverflow"
ScrollViewer.CanContentScroll="True"
ScrollViewer.VerticalScrollBarVisibility="Auto"
AcceptsReturn="True" AcceptsTab="True"
Text="{Binding Path=Text, UpdateSourceTrigger=PropertyChanged}"
IsEnabled="{Binding Path=TextBoxEnabled}"/>
Notice the Text property is bound as well; it is fully functional, which makes me think it is not a DataContext issue.
However, when I call this code:
private Boolean _textbox_enabled;
public Boolean Textbox_Enabled
{
get { return _textbox_enabled; }
set
{
OnPropertyChanged("TextBoxEnabled");
}
}
It does not work. To give further information, the TextBox_Enabled property is changed by this method:
public void DisabledTextBox()
{
this.Textbox_Enabled = false;
}
..which is called when a key combination is pressed.
Here are your little typos!
private Boolean _textbox_enabled;
public Boolean TextboxEnabled // here, underscore typo
{
get { return _textbox_enabled; }
set
{
_textbox_enabled = value; // You miss this line, could be ok to do an equality check here to. :)
OnPropertyChanged("TextboxEnabled"); //
}
}
Another thing for your xaml to update the text to the vm/datacontext
Text="{Binding Path=Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" IsEnabled="{Binding TextBoxEnabled}"/>

accessing to panel (view) object from the viewmodel

I just finished with watching practical mvvm presentation video on youtube and if I understand correctly moving logic from codebehing to view model is good practice and we should strive to this pattern.
Having this in mind I have one simple question. Inside xaml I have four radio buttons
<StackPanel x:Name="panel">
<RadioButton GroupName="myGroup" Name="Option1" Content="option one" IsChecked="True" Width="40"/>
<RadioButton GroupName="myGroup" Name="Option2" Content="option two" IsChecked="False" Width="80"/>
<RadioButton GroupName="myGroup" Name="Option3" Content="option three" IsChecked="False" Width="60"/>
</StackPanel>
I want to use this code inside viewmodel below to fetch selected radio btn.
var checkedValue = panel.Children.OfType<RadioButton>()
.FirstOrDefault(r => r.IsChecked.HasValue && r.IsChecked.Value);
Question is: How can I access to this panel object from the viewmodel? It's not data to use binding.
Update:
as #Rohit Vatss said "View objects should not be accessed from ViewModel" I would change question to How to know which radio button is selected using viewmodel?
You can do it by creating one property in you ViewModel, lets say GroupIndex
private int _groupIndex = 1;
public int GroupIndex
{
get { return _groupIndex; }
set
{
if (_groupIndex == value) return;
_groupIndex = value;
OnPropertyChanged("GroupIndex");
}
}
then create simple converter which will convert current GroupIndex value to true or false and back:
public class IndexBooleanConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null || parameter == null)
return false;
else
return (int)value == System.Convert.ToInt32(parameter);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null || parameter == null)
return null;
else if ((bool)value)
return System.Convert.ToInt32(parameter);
else
return DependencyProperty.UnsetValue;
}
}
and then bind your RadioButton to GroupIndex which will will be set to 1, 2 or 3 depending on which RadioButton is checked
<StackPanel>
<StackPanel.Resources>
<local:IndexBooleanConverter x:Key="IndexBooleanConverter"/>
</StackPanel.Resources>
<RadioButton Content="Option1" IsChecked="{Binding Path=GroupIndex, Converter={StaticResource IndexBooleanConverter}, ConverterParameter=1}"/>
<RadioButton Content="Option2" IsChecked="{Binding Path=GroupIndex, Converter={StaticResource IndexBooleanConverter}, ConverterParameter=2}"/>
<RadioButton Content="Option3" IsChecked="{Binding Path=GroupIndex, Converter={StaticResource IndexBooleanConverter}, ConverterParameter=3}"/>
</StackPanel>
In this case GroupIndex is int but you can also use same logic if for example your GroupIndex is an enum
Well an aprroach would be for example using a Command and a Command Parameter on the radiobuttons Binded to your viewmodel. For example:
<RadioButton GroupName="myGroup" Name="Option1" Content="option one" IsChecked="True" Width="40" Command="{Binding RbCheckedCommand}" CommandParameter="RB1"/>
<RadioButton GroupName="myGroup" Name="Option2" Content="option two" IsChecked="False" Width="80" Command="{Binding RbCheckedCommand}" CommandParameter="RB2"/>
<RadioButton GroupName="myGroup" Name="Option3" Content="option three" IsChecked="False" Width="60" Command="{Binding RbCheckedCommand}" CommandParameter="RB3"/>
Then on your ViewModel:
private readonly DelegateCommand<object> rbCheckedCommand;
public ICommand RbCheckedCommand
{
get { return this.rbCheckedCommand; }
}
private void RbCheckedCommandExecute(object obj)
{
string rbselected = obj.ToString();
}
And on the constructor of the class:
this.rbCheckedCommand = new DelegateCommand<object>(RbCheckedCommandExecute);
You will have to use the prism adding:
using Microsoft.Practices.Prism.Commands;
using Microsoft.Practices.Prism.ViewModel;
And making your class inherits from NotificationObject so you can use the Property changed easily.
Hope it helps.

WPF Combbox Wildcard Substring Search

I have the following properties set on my combobox-
<ComboBox ItemsSource="{Binding AllLines, Mode=OneWay}" Grid.Column="1" SelectedItem="{Binding SelectedLine}" Margin="4"
Visibility="{Binding ShowLines, Converter={StaticResource BoolToVisible}}" AlternationCount="2"
IsTextSearchEnabled="True" IsEditable="True" TextSearch.TextPath="SearchText" IsTextSearchCaseSensitive="False"
ItemContainerStyle="{StaticResource alternatingWithTriggers}">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock Margin="2,0,2,0" FontWeight="Bold" Text="{Binding Description}"
Visibility="{Binding Description, Converter={StaticResource NullVisibilityConverter}}"></TextBlock>
<TextBlock Margin="2,2,2,4" Text="{Binding Designator}"></TextBlock>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Following the suggestion outlined here I added a custom Search property that included the three properties I wanted to search against.
WPF: Changing a ComboBox's ItemTemplate removes the ability to jump down the list as you type. Any way to fix this?
public string SearchText {get { return string.Format("{0} | {1} | {2}", Description, ID, Designator); }}
My question is, can I do a wildcard or substring search on my concatenation of properties?
Found an idea here from which I modeled my solution-
http://jacobmsaylor.com/?p=17
I made some small changes such as listening to the KeyUp instead of the KeyDown and making the filter case-insensitive. I also added a check to make sure that the combo box text (the search text) was not null or empty.
In the code behind-
public SelectRouteSegmentDialog()
{
InitializeComponent();
LineComboBox.Items.Filter += FilterPredicate;
}
private bool FilterPredicate(object obj)
{
Line line = obj as Line;
if (string.IsNullOrEmpty(LineComboBox.Text)) return true;
if (line.SearchText != null)
{
if (line.SearchText.IndexOf(LineComboBox.Text, StringComparison.CurrentCultureIgnoreCase) >= 0)
{
return true;
}
return false;
}
else
{
//if the string is null, return false
return false;
}
}
private void combobox_KeyUp(object sender, KeyEventArgs e)
{
if ((e.Key == Key.Enter) || (e.Key == Key.Tab) || (e.Key == Key.Return))
{
//Formatting options
LineComboBox.Items.Filter = null;
}
else if ((e.Key == Key.Down) || (e.Key == Key.Up))
{
LineComboBox.IsDropDownOpen = true;
}
else
{
LineComboBox.IsDropDownOpen = true;
LineComboBox.Items.Filter += this.FilterPredicate;
}
}
And the xaml I set IsEditable=true, IsTextSearchEnabled=false and TextSearch.TextPath equal to the path I wanted displayed for my selected item (otherwise just the ToString was displayed). I also listend to the key up event-
<ComboBox ItemsSource="{Binding AllLines, Mode=OneWay}" Grid.Column="1" SelectedItem="{Binding SelectedLine}" Margin="4"
Visibility="{Binding ShowLines, Converter={StaticResource BoolToVisible}}" AlternationCount="2"
IsEditable="True" TextSearch.TextPath="SearchText" IsTextSearchEnabled="False"
ItemContainerStyle="{StaticResource alternatingWithTriggers}" x:Name="LineComboBox" KeyUp="combobox_KeyUp">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock Margin="2,0,2,0" FontWeight="Bold" Text="{Binding DisplayText}"
Visibility="{Binding Description, Converter={StaticResource NullVisibilityConverter}}"></TextBlock>
<TextBlock Margin="2,2,2,4" Text="{Binding Designator}"></TextBlock>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
My question is, can I do a wildcard or substring search on my concatenation of properties?
Not using the built-in TextSearch mechanism; it's a prefix match only. You can specify the text directly, or provide the path to the property containing the text (as you have done), but you cannot change the matching behavior.
You will have to implement your own text search mechanism to get the kind of behavior you want. Try exploring the TextSearch source code for implementation ideas.

Iterate through ComboBox items when using CheckBox as ItemTemplate

I using a ComboBox with CheckBox as ItemTemplate and I want to iterate through all items, get their checked status and write their content to a string if checked is true. The problem is that I am using a SqlDataReader to fill and bind the ComboBox from database and I can't find a way to access the items IsChecked property.
<ComboBox>
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox Click="CheckBox_Click" Content="{Binding}" IsChecked="{Binding Path=IsSelected, Mode=TwoWay}" Tag="{RelativeSource FindAncestor, AncestorType={x:Type ComboBox}}"/>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
I have tried casting the ComboBox items as CheckBoxes on the click event of them this way:
private void CheckBox_Click(object sender, RoutedEventArgs e)
{
for (int i = 0; i < myComboBox.Items.Count; i++)
{
CheckBox cb = (myComboBox.Items[i] as CheckBox);
if (cb.IsChecked == true)
{
myString += "," + myComboBox.SelectedItem.ToString() + "";
}
}
}
but cb always returns NULL. I am guessing it is something with the IsChecked property binding.
I'd like to get this working but I don't want to create an object/class to fill the combobox because I need it to be filled with database. I'd really appreciate any help.
You could do something like this (I'm not stick to MVVM pattern) and this is written on the fly :
public ArrayList List { get; set; }
public MainWindow()
{
InitializeComponent();
SqlDataReader rdr = cmd.ExecuteReader();
List = new ArrayList();
while (rdr.Read()){
List.Add(new Class{ Id = rdr.GetString(0), Value = rdr.GetString(1), IsChecked= rdr.GetString(1) as bool}); //this class will contain the same data schema in your datareader but using properties
}
rdr.Close();
DataContext = List;
}
<ComboBox Name="ComboBox" ItemsSource="{Binding}" >
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox Tag="{Binding Id}" Content="{Binding Name}" IsChecked="{Binding IsChecked}"/>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>

ComboBox SelectedItem binding not updating

I'm a bit puzzled:
this works:
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Label Content="Rol" />
<ComboBox ItemTemplate="{StaticResource listRollen}"
Height="23" Width="150"
SelectedItem="{Binding Path=SelectedRol, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
ItemsSource="{Binding Path=allRollen, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>
and the property for SelectedRol is:
public TblRollen SelectedRol
{
get { return _selectedRol; }
set
{
if (_selectedRol != value)
{
_selectedRol = value;
OnPropertyChanged("SelectedRol");
}
}
}
But this doesn't work:
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Label Content="Soort" />
<ComboBox ItemTemplate="{StaticResource listSoorten}"
Height="23" Width="150"
ItemsSource="{Binding Path=allSoorten}"
SelectedItem="{Binding Path=SelectedProduct, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</StackPanel>
with following property SelectedProduct:
public TblProduktSoorten SelectedProduct
{
get { return _selectedPSoort; }
set
{
if (_selectedPSoort != value)
{
_selectedPSoort = value;
OnPropertyChanged("SelectedProduct");
}
}
}
somewhere in my code I set SelectedProduct = p.TblProduktSoorten and while debugging, I see the property gets set correctly...
Combobox inside a DataGrid?
If the combobox is in a DataGrid you must add this :
Mode=TwoWay, UpdateSourceTrigger=PropertyChanged
See this : https://stackoverflow.com/a/5669426/16940
Try to use not selected item but value path look at the code sample
<ComboBox Name="projectcomboBox" ItemsSource="{Binding Path=Projects}" IsSynchronizedWithCurrentItem="True" DisplayMemberPath="FullName"
SelectedValuePath="Name" SelectedIndex="0" Grid.Row="1" Visibility="Visible" Canvas.Left="10" Canvas.Top="24" Margin="11,6,13,10">
</ComboBox>
the binding property is
public ObservableCollection<Project> Projects
{
get { return projects; }
set
{
projects = value;
RaisePropertyChanged("Projects");
}
}
This might be related to the fact that apparently attribute order does matter, in your second case the ItemsSource and SelectedItem declarations are swapped.
If you set the SelectedProduct property when SelectedProduct is changed in the property changed event handler, you need to set this property asynchronously.
private void ViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "SelectedProduct")
App.Current.Dispatcher.InvokeAsync(() => SelectedProduct = somevalue);
}
My problem was caused by my own tired brain. Same symptom, maybe it will kick you into seeing your problem.
Setting the SelectedItem must be given an item in the List!! (duhh) Normally this happens naturally but I had a case I got a "Role" from another service (Same object type) and was trying to set it and expecting the combobox to change! ;(
instead of -
Roles = roles;
CurrentRole = role;
remember to do this -
Roles = roles;
CurrentRole = roles.FirstOrDefault(e=> e.ID == role.ID); //(System.Linq)
I don't know if you fixed it yet, but I encountered the same issue today.
It was fixed by making sure the collection for selecteditems was an ObservableCollection.
I think this problem is caused by the type of ItemSource and SelectedItem is mitchmatched.
For example, if the ItemSource is binded to a List of int and the SelectedItem is binded to a string. If you set selected item to null or empty string, the combobox cannot know what item is selected. So the combobox will show nothing.
This might be old but I have not seen the trick that did it for me; I had to add NotifyOnSourceupdate=true to my SelectedItem in the ComboBox
This had me stumped for a while inside a DataGrid, using SelectedItem. Everything was fine but I am deserializing the app state which loads the items and also has a selected item. The collection was there but the selected isn't actually visible until I used the Text="{Binding Path=Score.SelectedResult.Offset}"
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox ToolTip="Score offset results"
ItemsSource="{Binding Score.SearchResults,UpdateSourceTrigger=PropertyChanged}"
SelectedItem="{Binding Score.SelectedResult, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Text="{Binding Path=Score.SelectedResult.Offset}"
SelectedValuePath="Offset"
DisplayMemberPath="Offset"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>

Categories