MultiBinding And MultiTrigger - wpf

...So I have 2 elements, i want that the IsChecked property of the checbox will binded to my
'IsAlwaysOn' property which is in my My Class object(Two Way), and to an element combox selected value properties, where if the value is 'enter', then IsChecked is false,
any ideas?

You can do this with a DataTrigger, however I wouldn't recommend it because the value of the CheckBox would not always get saved to MyClass.IsAlwaysOn
<Style x:Key="MyCheckBoxStyle" TargetType="{x:Type CheckBox}">
<Setter Property="IsChecked" Value="{Binding IsAlwaysOn}" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=MyComboBox, Path=SelectedValue}" Value="Enter">
<Setter Property="IsChecked" Value="False" />
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Style>
Instead, I would recommend handling this in the PropertyChange notification in MyClass. To prevent changes, I would either include a property in MyClass which determines if the CheckBox can be changed or not, or disable the CheckBox in a trigger like above.
void MyClass_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "SelectedComboBoxItem")
{
if (SelectedComboBoxItem == "Enter")
{
IsAlwaysOn = false;
CanChangeCheckBox = false;
}
else
{
CanChangeCheckBox = true;
}
}
}

Related

Uncheck checkbox when another is checked

I have two checkboxes. When I check one, I want the other to uncheck if it's currently checked. Both can be unchecked. Currently, I can check one, but when I check the other, both of them uncheck. I'm having trouble figuring out why.
Note: I want to do this all in the .xaml if possible. I've been messing with data triggers to get the proper effect with no luck so far.
<CheckBox Name="SYOChkBox">
<CheckBox.Style>
<Style TargetType="CheckBox">
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, ElementName=UTMChkBox}"
Value="True">
<Setter Property="IsChecked"
Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</CheckBox.Style>
</CheckBox>
<CheckBox Name="UTMChkBox">
<CheckBox.Style>
<Style TargetType="CheckBox">
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, ElementName=SYOChkBox}"
Value="True">
<Setter Property="IsChecked"
Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</CheckBox.Style>
</CheckBox>
You should really be using a ViewModel to do this (I'll leave a snippet on how you could do it using a VM at the end of the post).
Anyway, here's what I was able to do with XAML only
Using CheckBox
The problem with using this approach is that when both are checked, both of the triggers will be triggered (??), and both will be unchecked. So, I guess what you can do is this:
CheckBox X will normally uncheck when you check CheckBox Y, but CheckBox X just won't check while CheckBox Y is checked.
<CheckBox Name="SYOChkBox">
<CheckBox.Style>
<Style TargetType="CheckBox">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding IsChecked, ElementName=UTMChkBox}" Value="True" />
<Condition Binding="{Binding IsChecked, ElementName=SYOChkBox}" Value="True" />
</MultiDataTrigger.Conditions>
<Setter Property="IsChecked" Value="False" />
</MultiDataTrigger>
</Style.Triggers>
</Style>
</CheckBox.Style>
</CheckBox>
<CheckBox Name="UTMChkBox" />
Using RadioButton
I know it isn't what you asked, but as a sugestion, you could use a RadioButton, the code would be a lot cleaner:
<RadioButton>Option A</RadioButton>
<RadioButton>Option B</RadioButton>
<RadioButton>None</RadioButton>
Using ViewModel
XAML
<CheckBox IsChecked="{Binding IsChecked_CheckBoxA}" />
<CheckBox IsChecked="{Binding IsChecked_CheckBoxB}" />
Code-behind:
private bool _IsChecked_CheckBoxA;
private bool _IsChecked_CheckBoxB;
public bool IsChecked_CheckBoxA
{
get
{
return _IsChecked_CheckBoxA;
}
set
{
if (value)
IsChecked_CheckBoxB = false;
_IsChecked_CheckBoxA = value;
NotifyPropertyChanged();
}
}
public bool IsChecked_CheckBoxB
{
get
{
return _IsChecked_CheckBoxB;
}
set
{
if (value)
IsChecked_CheckBoxA = false;
_IsChecked_CheckBoxB = value;
NotifyPropertyChanged();
}
}
As others have said, it might not be doable in just xaml, and using a viewmodel is suggested. So here's what I have that works:
Xaml:
<CheckBox Name="SYOChkBox"
IsChecked="{Binding IsCheckedSYO}" />
<CheckBox Name="UTMChkBox"
IsChecked="{Binding IsCheckedUTM}" />
Viewmodel:
private bool _isCheckedSYO;
public bool IsCheckedSYO
{
get { return _isCheckedSYO; }
set
{
if (true == value) //if checked
{
IsCheckedUTM = false; //uncheck the UTM check box
_isCheckedSYO = value;
}
else
{
_isCheckedSYO = value;
}
OnPropertyChanged("IsCheckedSYO");
}
}
private bool _isCheckedUTM;
public bool IsCheckedUTM
{
get { return _isCheckedUTM; }
set
{
if (true == value) //if checked
{
IsCheckedSYO = false; //uncheck the SYO checkbox
_isCheckedUTM = value;
}
else
{
_isCheckedUTM = value;
}
OnPropertyChanged("IsCheckedUTM");
}
}

Hiding context menu based on data trigger

I have a couple of grids in a user control. I want to hide the context menu in a grid based on a property in the DataContext. I have this code:
<Style TargetType="{x:Type ContextMenu}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsLockedNorthGrid}" Value="False">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
I know the IsLockedNorthGrid property works since I'm using it somewhere else in xaml. What am I missing?
Thanks
If you are using Style.Triggers to change the Visibility, be sure you are not setting Visibility to Context Menu inline. Since, inline property has higher priority over the style.
Check if the Visibility is set to a specific value (setting it in a specific element and triggering it won´t work). Also try
<Style TargetType="{x:Type ContextMenu}">
<Setter Property="Visibility" Value="Visible" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsLockedNorthGrid}" Value="False">
<Setter Property="Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
I was able to solve my problem like so:
<XamDataGrid ContextMenuOpeninig="OnContextMenuOpening">
<XamDataGrid.Resources>
<ContextMenu x:Key="GridContextMenu">...</ContextMenu> </XamDataGrid.Resources>
<XamDataGrid>
Code behind:
private void OnContextMenuOpening(object sender, ContextMenuEventArgs e)
{
var logViewModel = (LogViewModelBase)DataContext;
var grid = sender as XamDataGrid;
var menu = grid.Resources["GridContextMenu"] as ContextMenu;
menu.Visibility = !logViewModel.IsLockedNorthGrid ? Visibility.Hidden : Visibility.Visible;
}
Not that pretty but it works.

Grid Hide/Show animation

I've got some User Control, which is grid with transparent background, on top of that there's another grid that is suppose to change its width when triggers are fired (ultimately it'll be a in/out animation). Purpose was to simply use something different than Visibility that was instantly hiding entire control without any animations Here's the property it's based on:
public static readonly DependencyProperty IsOpenedProperty = DependencyProperty.Register ("IsOpened", typeof (Boolean), typeof (SidePanel), new PropertyMetadata (false));
public bool IsOpened {
get {
if (GetValue (IsOpenedProperty) != null)
return (bool)GetValue (IsOpenedProperty);
else
return false;
}
set {
SetValue (IsOpenedProperty, value);
Console.WriteLine(value);
}
}
And the Grid itself:
<Grid>
<Grid.Style>
<Style TargetType="{x:Type Grid}">
<Setter Property="Width" Value="50"/>
<Setter Property="Background" Value="Gray"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsOpened}" Value="True">
<Setter Property="Width" Value="350"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsOpened}" Value="False">
<Setter Property="Width" Value="0"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Style>
<TextBlock Text="{Binding ElementName=Side, Path=Width}"/>
</Grid>
Console gives me corect output but triggers don't fire at all.
Just checked one more thing and when I set trigger for x:Null value then it's fired all the time, how is it possible as Get shouldn't ever return null value here?
Alright I just gave up on dependency property here, created private variable to hold the value and added data context with INotifyPropertyChanged interface implementation and now it works.

TextBox's Text set through DataTrigger not updating the property value in Model

I am new to WPF and I want to clear a textBox's value if a check box is unchecked. I tried doing that through data triggers.
Below is the code:
<TextBox Text="{Binding Path=Amount,Mode=TwoWay}">
<TextBox.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsSelected}" Value="false">
<Setter Property="TextBox.Text" Value="{x:Null}"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
My checkbox's value is set in "IsSelected" property of My Model. Here, if the checkbox is unchecked, then the text's updated value, which is {x:Null} in this case, is not reflecting in "Amount" property of my Model. Because of this the text never seems to be changed on the UI. The "Amount" earlier set value is getting set again in the TextBox because of binding
Any help is appreciated. Let me know in case you need any more information or clarification
Thanks.
In such cases I normally prefer ViewModel / Model doing the "clear" part of the functionality,
hence in your case I'd normally do something like:
public bool IsSelected {
get {
return _isSelected;
}
private set {
if (value == _isSelected)
return;
RaisePropertyChanging(() => IsSelected);
_isSelected = value;
RaisePropertyChanged(() => IsSelected);
if (_isSelected == false)
Amount = string.Empty
}
}
That way the View does not hold responsibility for any logic and thus doesn't need the DataTrigger at all
Update:
The Problem with your code is when you set the Text with a Binding in the TextBox it takes precedence over the value you set in the Style for the Text property. You can check this by using this:
<TextBox>
<TextBox.Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="Text"
Value="{Binding Path=Amount,
Mode=TwoWay}" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsSelected}"
Value="false">
<Setter Property="Text"
Value="{x:Null}" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
This will now clear the Text when the CheckBox is checked, however it will not be updating your Binding(Amount) since essentially your Binding is only active when the CheckBox is selected.

How to highlight a gridview row if some object value is greater than another?

would like to know how to highlight a gridview row if some object value is greater than another ? (Consider the gridview to be bind to an observablecollection)
Thanks.
Put a property on the class of the items in your observable collection that will get set to true/false based on the comparison you need. Then you should be able to bind to this property in a DataTrigger for a Style on the DataGrid's ItemContainerStyle.
Try this...
<DataGrid ItemsSource="{Binding YourObservableCollection}" >
<DataGrid.ItemContainerStyle>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding YourShouldHighlightProperty}" Value="True">
<Setter Property="Control.Background" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.ItemContainerStyle>
</DataGrid>
You will need to implement a converter to do a > comparison but this shows a highlight
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsParent}" Value="True">
<Setter Property="Background" Value="Gainsboro" />
</DataTrigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
Use the following code.It wored for me.
private void DataGrid_LoadingRow(object sender, DataGridRowEventArgs e)
{
try
{
foreach (loadtodatagrid item in gridview.ItemsSource)
{
var row = gridview.ItemContainerGenerator.ContainerFromItem(item) as DataGridRow;
if (item.item1== item.item2)
{
row.Background = new SolidColorBrush(Colors.Yellow);
}
else
{
// row.Background = new SolidColorBrush(Colors.Green);
}
}
}
catch(Exception ep)
{
//do nothing....
}
LoadingRow="DataGrid_LoadingRow" to datagrid in WPF

Resources