WPF. Check and disable a checkbox if another checkbox is checked - wpf

I have 2 checkboxes.
when one is checked, the other one must be checked and disabled.
The code I have so far is like so
Xaml
<CheckBox x:Name="chkSABranches" Content="Apply to all branches" IsChecked="{Binding IsSABranches,ElementName=pgPageTemplate}" Grid.Row="0" Grid.Column="2"/>
In xaml.cs:
public static DependencyProperty IsSABranchesProperty = DependencyProperty.Register("IsSABranches", typeof(bool), typeof(pgAccounts), new PropertyMetadata(false));
public static DependencyProperty IsSAWarehousesProperty = DependencyProperty.Register("IsSAWarehouses", typeof(bool), typeof(pgAccounts), new PropertyMetadata(false));
public Boolean IsSABranches
{
get
{
return (bool)GetValue(IsSABranchesProperty);
}
set
{
SetValue(IsSABranchesProperty, value);
NotifyPropertyChanged("IsSABranches");
NotifyPropertyChanged("IsSAWarehouses");
}
}
public Boolean IsSAWarehouses
{
get
{
return (bool)GetValue(IsSAWarehousesProperty) || (bool)GetValue(IsSABranchesProperty);
}
set
{
SetValue(IsSAWarehousesProperty, value);
NotifyPropertyChanged("IsSAWarehouses");
}
}
This doesn't seem to work.. Could anyone please provide some guidance. thanks

Here how to do it entirely in Xaml using DataTrigers
<StackPanel>
<CheckBox x:Name="CheckBox1"></CheckBox>
<CheckBox >
<CheckBox.Style>
<Style TargetType="CheckBox">
<Setter Property="IsEnabled" Value="True"></Setter>
<Setter Property="IsChecked" Value="False"></Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked,ElementName=CheckBox1}" Value="True">
<Setter Property="IsChecked" Value="True"/>
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
</Style.Triggers>
</Style>
</CheckBox.Style>
</CheckBox>
</StackPanel>

Related

WPF Button with hot image

<Button Margin="10,0,2,0" Width="90" Command="Open">
<Button.Style>
<Style TargetType="Button">
<Setter Property="Content" Value="{Binding Source={StaticResource tstImage}}"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Content" Value="{Binding Source={StaticResource tstImage1}}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Content" Value="{Binding Source={StaticResource tstImage2}}"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
I would like to create a button support hot image: When the mouse hover on the button, the image changes to another one.
I implement a button instance with above code. But actually I would like to create a template that every button can use this style. It is cumbersome to write the same style for every button.
I think it should like:
<Style TargetType="Button">
<Setter Property="Content" Value="{Binding Source= normalImage"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Content" Value="{Binding Source=hotImage"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Content" Value="{Binding Source=disableImage"/>
</Trigger>
</Style.Triggers>
</Style>
And then use the style like:
<Button command="Open" normalImage="icon1.png" hotImage="icon2.png" disableImage="icon3.png"/>
I am a fresher to WPF, I have tried many ways to do that but still stuck in this problem.
I would like to create a template or style that can apply to every button. The second and third snippet is what I want to achieve. But it not works. In the second snippet, the normalImage,hotImage and disableImage are dynamic paths that can be specified by buttons just as what I wrote in the third snippet.
Please help. Thanks.
I am trying to use attached-property, but I met another problem:
Style binding attached-property didn't show up anything
I solve it myself by using attached property. It may help others, so I post out my code.
Firstly, create the attached property:
class ImageAttached : DependencyObject
{
public static Image GetNormalImage(DependencyObject obj)
{
return (Image)obj.GetValue(NormalImageProperty);
}
public static void SetNormalImage(DependencyObject obj, Image value)
{
obj.SetValue(NormalImageProperty, value);
}
// Using a DependencyProperty as the backing store for NormalImage. This enables animation, styling, binding, etc...
public static readonly DependencyProperty NormalImageProperty =
DependencyProperty.RegisterAttached("NormalImage", typeof(Image), typeof(ImageAttached), new PropertyMetadata((Image)null));
public static Image GetHotImage(DependencyObject obj)
{
return (Image)obj.GetValue(HotImageProperty);
}
public static void SetHotImage(DependencyObject obj, Image value)
{
obj.SetValue(HotImageProperty, value);
}
// Using a DependencyProperty as the backing store for HotImage. This enables animation, styling, binding, etc...
public static readonly DependencyProperty HotImageProperty =
DependencyProperty.RegisterAttached("HotImage", typeof(Image), typeof(ImageAttached), new PropertyMetadata((Image)null));
public static Image GetDisableImage(DependencyObject obj)
{
return (Image)obj.GetValue(DisableImageProperty);
}
public static void SetDisableImage(DependencyObject obj, Image value)
{
obj.SetValue(DisableImageProperty, value);
}
// Using a DependencyProperty as the backing store for DisableImage. This enables animation, styling, binding, etc...
public static readonly DependencyProperty DisableImageProperty =
DependencyProperty.RegisterAttached("DisableImage", typeof(Image), typeof(ImageAttached), new PropertyMetadata((Image)null));
}
Secondly, create a style target to a button:
<Style x:Key="btnStyle" TargetType="{x:Type Button}">
<Setter Property="Content" Value="{Binding Path=(local:ImageAttached.NormalImage), RelativeSource={RelativeSource Self}}"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Content" Value="{Binding Path=(local:ImageAttached.HotImage), RelativeSource={RelativeSource Self}}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Content" Value="{Binding Path=(local:ImageAttached.DisableImage), RelativeSource={RelativeSource Self}}"/>
</Trigger>
</Style.Triggers>
</Style>
Lastly, use it. e.g:
<Button x:Name="btn1" Click="Button_Click_1" Width="100" Height="48" Style="{DynamicResource btnStyle}"
local:ImageAttached.NormalImage="{StaticResource tstImage}"
local:ImageAttached.HotImage="{StaticResource tstImage2}"
local:ImageAttached.DisableImage="{StaticResource tstImage1}"/>

User Control - dependency property to Change Image Issues

i'm having issues setting the Image from a dependency property. It seems like the trigger doesnt fire. I just want hide/show and image, or set the source if possible.
public static readonly DependencyProperty HasSingleValueProperty =
DependencyProperty.Register("HasSingleValue", typeof(bool), typeof(LevelControl), new
FrameworkPropertyMetadata(false,FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public bool HasSingleValue
{
get { return (bool)GetValue(HasSingleValueProperty); }
set { SetValue(HasSingleValueProperty, value); }
}
public LevelControl()
{
this.InitializeComponent();
//this.DataContext = this;
LayoutRoot.DataContext = this;
}
//Control Markup
<Grid x:Name="LayoutRoot">
<Image x:Name="xGreenBarClientTX" HorizontalAlignment="Stretch" Height="13" Margin="7,8.5,7,0"
Stretch="Fill"
VerticalAlignment="Top"
Width="47"
Canvas.Left="181.67"
d:LayoutOverrides="Height" >
<Image.Style>
<Style TargetType="{x:Type Image}">
<Style.Triggers>
<DataTrigger Binding="{Binding HasSingleValue}" Value="True">
<Setter Property="Opacity" Value="100"/>
</DataTrigger>
<DataTrigger Binding="{Binding HasSingleValue}" Value="False">
<Setter Property="Opacity" Value="0"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
Here we go
you have to update your binding as follows (I used Ellipse instead for testing)
<Window
x:Name="myWindow">
<Style TargetType="{x:Type Ellipse}">
<Style.Triggers>
<DataTrigger Binding="{Binding HasSingleValue, ElementName=myWindow}" Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
<DataTrigger Binding="{Binding HasSingleValue, ElementName=myWindow}" Value="False">
<Setter Property="Visibility" Value="Hidden"/>
</DataTrigger>
</Style.Triggers>
</Style>
Then you need to set HasSingleValue
I created two buttons to show and hide my Ellipse.
I think the trouble may be with how you're trying to update the dependency property because I've made a slight alteration to your example to verify the bindings and such do work as expected. I had suspected that there may be a problem with binding to a property on the grid's data context from the image, but that appears to be fine.
It wasn't clear what kind of class you were providing as a data context, but if you're using dependency properties then it needs to be a DependencyObject.
I've provided an example here using a text block and a toggle button to change the dependency property. (assuming you're using code-behind)
<Grid x:Name="LayoutRoot">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="xGreenBarClientTX" HorizontalAlignment="Stretch" Height="13" Margin="7,8.5,7,0"
VerticalAlignment="Top"
Width="200"
Canvas.Left="181.67" >
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding HasSingleValue}" Value="True">
<Setter Property="Text" Value="Is Set"/>
</DataTrigger>
<DataTrigger Binding="{Binding HasSingleValue}" Value="False">
<Setter Property="Text" Value="Is Not Set"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
<Button Grid.Column="1" Content="Toggle" Click="Button_Click" VerticalAlignment="Top" HorizontalAlignment="Left"/>
</Grid>
and the code-behind:
public MainWindow()
{
InitializeComponent();
LayoutRoot.DataContext = new VM() { HasSingleValue = true };
}
private void Button_Click( object sender, RoutedEventArgs e )
{
var vm = LayoutRoot.DataContext as VM;
if ( vm == null )
return;
vm.HasSingleValue = !vm.HasSingleValue;
}
public class VM : DependencyObject
{
public static readonly DependencyProperty HasSingleValueProperty =
DependencyProperty.Register( "HasSingleValue", typeof( bool ), typeof( VM ), new FrameworkPropertyMetadata( false, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault ) );
public bool HasSingleValue
{
get { return (bool) GetValue( HasSingleValueProperty ); }
set { SetValue( HasSingleValueProperty, value ); }
}
}

Growing UserControl Size with Style Trigger?

I would like to cause a custom UserControl to grow by a multiplier when an "IsSelected" DP is set to true. My current XAML looks like this:
<ctrl:MyBaseControl x:Class="MyDemo.Controls.MyCustomControl"
...>
<ctrl:MyBaseControl.Resources>
<Style TargetType="{x:Type ctrl:MyCustomControl}">
<Setter Property="BorderBrush" Value="White" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="BorderThickness" Value="2" />
<Setter Property="Width" Value="340" />
<Setter Property="Height" Value="260" />
</Trigger>
</Style.Triggers>
</Style>
</ctrl:MyBaseControl.Resources>
<Border>
<StackPanel>
...
</StackPanel>
</Border>
In the above sample, "MyBaseControl" extends UserControl, and defines the IsSelected DP.
This code just plain isn't working at the moment, which is one of my issues. The other is that I would like to grow the Width/Height for a certain amount (for example: 0.10) instead of setting it to a hard number. This way I can set the size when I define the control at the source.
Thanks for any help!
ADDITION CODE:
MyBaseControl Code:
public abstract class MyBaseControl: UserControl
{
public static readonly DependencyProperty IsSelectedProperty =
DependencyProperty.Register(
"IsSelected",
typeof(Boolean),
typeof(MyBaseControl),
new PropertyMetadata(null));
public MyBaseControl() : base() { }
#region Properties
public Boolean IsSelected
{
get { return (Boolean)GetValue(IsSelectedProperty); }
set { SetValue(IsSelectedProperty, value); }
}
#endregion Properties
}
MyCustomControl Code:
public partial class MyCustomControl: MyBaseControl
{
public static readonly DependencyProperty IconProperty =
DependencyProperty.Register(
"Icon",
typeof(ImageSource),
typeof(MyCustomControl),
new PropertyMetadata(null));
public static readonly DependencyProperty BlurbProperty =
DependencyProperty.Register(
"Blurb",
typeof(String),
typeof(MyCustomControl),
new PropertyMetadata(null));
public MyCustomControl()
{
InitializeComponent();
}
#region Properties
public ImageSource Icon
{
get { return (ImageSource)GetValue(IconProperty); }
set { SetValue(IconProperty, value); }
}
public String Blurb
{
get { return (String)GetValue(BlurbProperty); }
set { SetValue(BlurbProperty, value); }
}
#endregion Properties
}
Example of working trigger on internal elements:
<Style TargetType="{x:Type Border}">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ctrl:MyCustomControl}}, Path=IsSelected}" Value="True">
<Setter Property="BorderThickness" Value="5" />
</DataTrigger>
</Style.Triggers>
</Style>
Try this
<ctrl:MyBaseControl.Resources>
<Style TargetType="{x:Type ctrl:MyCustomControl}">
<Setter Property="BorderBrush" Value="White" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="BorderThickness" Value="2" />
<Setter Property="RenderTransform" >
<Setter.Value>
<ScaleTransform ScaleX="1.1" ScaleY="1.1" />
</Setter.Value>
</Setter>
<Setter Property="RenderTransformOrigin" Value="0.5, 0.5"/>
</Trigger>
</Style.Triggers>
</Style>
</ctrl:MyBaseControl.Resources>

Resource 1 works, 2 doesn't

<ToggleButton Command="{Binding Path=Command}" Content="{Binding Path=DisplayName}" Template="{Utilities:BindableResource {Binding Path=TemplateResource}}">
<ToggleButton.Style>
<Style TargetType="ToggleButton">
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Template" Value="{Utilities:BindableResource {Binding Path=SelectedTemplateResource}}" />
</Trigger>
</Style.Triggers>
</Style>
</ToggleButton.Style>
</ToggleButton>
The first bindable resource works for "TemplateResource" on the template property of togglebutton however "SelectedTemplateResource" does not work within the tiggers setter. This code is within a resourcedictionary where the actual resource is within a themed resourcedictionary.
I get an error saying key is null for xamlparseexception for the setter value. I've been stairing at this for hours but cannot figure out why it doesn't work... If I take out the style and replace the first binding with the second resource it does display proper however the binding within the style will not work.
Does anybody have any idea why?
EDIT
I just tried this but no luck.
<ToggleButton Command="{Binding Path=Command}" Content="{Binding Path=DisplayName}">
<ToggleButton.Style>
<Style TargetType="ToggleButton">
<Style.Triggers>
<Trigger Property="IsChecked" Value="False">
<Setter Property="Template" Value="{Utilities:BindableResource {Binding Path=TemplateResource}}" />
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Template" Value="{Utilities:BindableResource {Binding Path=SelectedTemplateResource}}" />
</Trigger>
</Style.Triggers>
</Style>
</ToggleButton.Style>
</ToggleButton>
After finding out this really is not possible to do in pure xaml I brought out the c# and create a custom control... this is very basic and can be improved on and I will have change a bit of it but ultimately a custom control solves the issue so that you can hit the click event from within the resource dictionary and change the template on the fly.
public class TabButton : Button
{
public static readonly DependencyProperty SelectedTemplateProperty =
DependencyProperty.Register("SelectedTemplate", typeof(ControlTemplate), typeof(TabButton));
public ControlTemplate SelectedTemplate
{
get { return base.GetValue(SelectedTemplateProperty) as ControlTemplate; }
set { base.SetValue(SelectedTemplateProperty, value); }
}
public TabButton()
{
this.Click += new RoutedEventHandler(TabButton_Click);
}
~TabButton()
{
}
public void TabButton_Click(object sender, RoutedEventArgs e)
{
ControlTemplate template = (ControlTemplate)this.FindResource("Environmental Template Selected");
(sender as TabButton).Template = template;
}
}
Cheers.

Using custom dependency properties as DataTrigger in WPF

I have a custom dependency property that I would like to use as a data trigger. Here is the code behind:
public static readonly DependencyProperty BioinsulatorScannedProperty =
DependencyProperty.Register(
"BioinsulatorScanned",
typeof(bool),
typeof(DisposablesDisplay),
new FrameworkPropertyMetadata(false));
public bool BioinsulatorScanned
{
get
{
return (bool)GetValue(BioinsulatorScannedProperty);
}
set
{
SetValue(BioinsulatorScannedProperty, value);
}
}
I have created a style and control template. My goal is to change the color of some text when the dependency prop is set to true...
<Style x:Key="TreatEye" TargetType="Label">
<Setter Property="Foreground" Value="#d1d1d1" />
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="FontSize" Value="30" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Label">
<Canvas>
<TextBlock x:Name="bioinsulatorText"
Canvas.Left="21" Canvas.Top="33"
Text="Bioinsulator" />
<TextBlock Canvas.Left="21" Canvas.Top="70"
Text="KXL Kit" />
</Canvas>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding BioinsulatorScanned}"
Value="True">
<Setter TargetName="bioinsulatorText"
Property="Foreground" Value="Black" />
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Despite successfully setting the dependency prop to true programmatically, This trigger condition never fires. This is a real pain to debug!
Thanks in advance.
In this case I am switching the visibility of a button using a datatrigger based on a dependency property FirstLevelProperty.
public static readonly DependencyProperty FirstLevelProperty = DependencyProperty.Register("FirstLevel", typeof(string), typeof(MyWindowClass));
public string FirstLevel
{
get
{
return this.GetValue(FirstLevelProperty).ToString();
}
set
{
this.SetValue(FirstLevelProperty, value);
}
}
You can reference the dependency property FirstLevel(Property) contained (in this case) in a window by using the RelativeSource binding. Also you should set the default setting in the style, that will be overridden by the datatrigger.
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<DataTrigger
Binding="{Binding Path=FirstLevel,
RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type Window}}}"
Value="SomeValue">
<Setter Property="Visibility"
Value="Hidden" />
</DataTrigger>
</Style.Triggers>
<Setter Property="Visibility" Value="Visible" />
</Style>
</Button.Style>
It looks like your dependency property is defined inside a DisposableDisplay object that you created. In order for the binding specified to work, an instance of that DisposableDisplay object must be set as the DataContext of the control (label in this case) or any of its ancestors.

Resources