I want to set property IsEnabled of button based on switch and picker using binding. Something like this:
XAML:
<Button Text="Start tracking"
AbsoluteLayout.LayoutBounds="0, 1, 1, 0.1"
AbsoluteLayout.LayoutFlags="All"
x:Name="startTrackingButton"
IsEnabled="{Binding}"
Clicked="StartTracking_Clicked"
VerticalOptions="CenterAndExpand"/>
Code behind:
startTrackingButton.BindingContext = (!autoTrackingSwitch.IsToggled || frequencyPicker.IsSet);
This solution does not work. How can I do it? Thank you.
Try using Style:
<Style TargetType="Button">
<Style.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<BindingCondition Binding="{Binding Source={x:Reference autoTrackingSwitch}, Path=IsToggled}" Value="True"/>
<BindingCondition Binding="{Binding Source={x:Reference frequencyPicker}, Path=IsSet}" Value="True"/>
</MultiTrigger.Conditions>
<Setter Property="Enabled" Value="True"/>
</MultiTrigger>
</Style.Triggers>
</Style>
You can specify it inside Button.Resources of your button.
Related
i want to Change Visibility of TextBlock when Text property is null or empty in wpf we can do this easily:
<Style TargetType = "TextBlock">
<Setter Property = "Visibility" Value = "Visibile" />
<Style.Triggers>
<Trigger Property = "Text" Value = "">
<Setter Property = "Visibility" Value = "Collapsed" />
</Trigger>
</Style.Triggers>
</Style>
but triggers is not available in uwp, how can i do this in uwp?
<Interactivity:Interaction.Behaviors>
<Core:DataTriggerBehavior Binding="{Binding Text, ElementName=txt}" ComparisonCondition="Equal" Value="">
<Core:ChangePropertyAction TargetObject="{Binding ElementName=txt}" PropertyName="Visibility" Value="Collapsed" />
</Core:DataTriggerBehavior>
</Interactivity:Interaction.Behaviors>
I have a TextBox bound to a decimal value which I want to format to not display decimal values if they are zero. At the same time I want to change the Background to a color if the property value is zero and another boolean property is true.
I have managed to achieve both but not together. If I remove the StringFormat from the Text Binding below the Background works perfectly but a value of, for example, 10 is displayed as 10.00, which I don't want. With the StringFormat the Background is not set and the TextBox is empty when 0 and suppresses decimals if they are zero, as required (empty string for zero is acceptable). So I assume it has to do with the empty string. I did try to test for an empty string with Path=Text.IsEmpty and value="True" as suggested in another post but that gives a design time error that Property IsEmpty is not found on type String.
This is what I have so far:
<TextBox x:Name="FactorValueTextBox" Text="{Binding Value, StringFormat={}{0:# ###.##}}" IsReadOnly="{Binding CommodityGradingFactor.Total}" GotKeyboardFocus="GradeFactorGotKeyboardFocus">
<TextBox.Style>
<Style TargetType="TextBox">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding RelativeSource={RelativeSource Mode=Self}, Path=Text}" Value="0"/>
<Condition Binding="{Binding CommodityGradingFactor.Manditory}" Value="True"/>
</MultiDataTrigger.Conditions>
<Setter Property="Background" Value="LightPink"/>
</MultiDataTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="True"/>
<Condition Property="IsReadOnly" Value="False"/>
</MultiTrigger.Conditions>
<Setter Property="FontSize" Value="15"/>
<Setter Property="FontWeight" Value="Bold"/>
</MultiTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
For completeness the GotKeyboardFocus() function simply selects the current value when the user tabs into the TextBox:
private void GradeFactorGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
if (e.KeyboardDevice.IsKeyDown(Key.Tab))
((TextBox)sender).SelectAll();
}
Instead of binding the condition to the property Text
<Condition Binding="{Binding RelativeSource={RelativeSource Mode=Self}, Path=Text}" Value="0"/>
Why not binding it to the property Value
<Condition Binding="{Binding Value}" Value="0"/>
Note:
Depending on your use case, you may want to implement INotifyPropertyChanged on your Value property, avoid naming your backfield property as "value" since it is a Contextual keywords
for INotifyPropertyChanged case.
I want to define triggers as resources to use them later in my controls.
Like this:
<Window.Resources>
<DataTrigger x:Key="Trigger1" Binding="{Binding ViewModelProperty1}" Value="Val1">
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
<DataTrigger x:Key="Trigger2" Binding="{Binding ViewModelProperty2}" Value="Val2">
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
...
</Window.Resources>
However, when I try to run the code, the compiler complains that IsEnabled is not a valid member. I think this is because it cannot know if the control in question will even have the property "IsEnabled". Like with styles, I think I need to somehow specifiy the TargetType (which would be, in my case, FrameworkElement). But how?
NOTE:
Please do not suggest to use styles instead of triggers as resources. Since a control can only have ONE style, but I need to give SEVERAL triggers to one control, styles are no option here:
In my actual code I have a Button that should have trigger 1, 2 and 4 and a TextBox that should have trigger 1 and 3 and a Label that should have trigger 2, 3 and 4... I think you get it.
You can do it like this (note how I prepend IsEnabled with FrameworkElement and also how I reference those resources from style triggers):
<Window.Resources>
<DataTrigger x:Key="Trigger1"
Binding="{Binding ViewModelProperty1}"
Value="Val1">
<Setter Property="FrameworkElement.IsEnabled"
Value="False" />
</DataTrigger>
<DataTrigger x:Key="Trigger2"
Binding="{Binding ViewModelProperty2}"
Value="Val2">
<Setter Property="FrameworkElement.IsEnabled"
Value="False" />
</DataTrigger>
</Window.Resources>
<Button>
<Button.Style>
<Style>
<Style.Triggers>
<StaticResource ResourceKey="Trigger1" />
<StaticResource ResourceKey="Trigger2" />
</Style.Triggers>
</Style>
</Button.Style>
</Button>
I have the following style defined in my XAML to enable buttons only when something in the DataContext has changed (IsDirty = true) :
<!-- Style for Buttons to enable based on IsDirty value -->
<Style x:Key="EnableWhenDirtyButtonStyle" TargetType="{x:Type Button}"
BasedOn="{StaticResource ButtonStyle}">
<Setter Property="IsEnabled" Value="False" />
<Style.Triggers>
<!-- Enable button when something has changed -->
<DataTrigger Binding="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type UserControl}}, Path=DataContext.IsDirty}" Value="True">
<Setter Property="Button.IsEnabled" Value="true" />
</DataTrigger>
</Style.Triggers>
</Style>
This works as long as there is only one DataContext within the UserControl. I now have the situation where I have 3 different DataViews so I have 3 different IsDirty values (i.e., CustomerTableIsDirty, OrderTableIsDirty, OrderDetailTableIsDirty). In this case I can create three new *DisableWhenDirtyButtonStyle in the UserControl like:
<Style x:Key="CustomerTableEnableWhenDirtyButtonStyle"
TargetType="{x:Type Button}"
BasedOn="{StaticResource ButtonStyle}">
<Setter Property="Button.IsEnabled" Value="False" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=CustomerTableIsDirty}" Value="true">
<Setter Property="Button.IsEnabled" Value="True" />
</DataTrigger>
</Style.Triggers>
</Style>
Is there a way to create a DataTrigger such that the binding value can be passed into the style as a parameter?
Alternatively, is there a way to add conditions to a MultiDataTrigger when inheriting a style via 'BasedOn' which would already have a MultiDataTrigger defined. For instance:
<Style x:Key="CustomerTableEnableWhenDirtyButtonStyle"
TargetType="{x:Type Button}"
BasedOn="{StaticResource EnableWhenDirtyButtonStyle}">
<!-- Add the following to existing MultiDataTrigger in EnableWhenDirtyButtonStyle -->
<Condition Binding="{Binding Path=CustomerTableIsDirty}" Value="true" />
</Style>
I CANNOT use MultiBinding as this style is part of a base project which gets used by multiple other projects (as a DLL). The users of this DLL would not be able to update the style to include the necessary Binding Path.
Instead of using 3 different names, just use a single name IsDirty.
I have implemented a WPF user control and what i want to achieve here is on mouseover on Main Grid some stack panels should hide. And i need to have multiple triggers conditions. Despite looking everywhere i am unable to find what am i doing wrong. UserControl Resources are as follow
<UserControl.Resources>
<Style x:Key="StackViewStyle" TargetType="{x:Type StackPanel}">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding RelativeSource={RelativeSource AncestorType=Grid},Path=IsMouseOver}" Value="True" />
<Condition Binding="{Binding Path=FileState, RelativeSource={RelativeSource Self}}" Value="Uploading" />
</MultiDataTrigger.Conditions>
<Setter Property="Visibility" Value="Collapsed"/>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</UserControl.Resources>
Data binding is working fine, because when i put in a test label to check its value it was "uploading". If i remove FileState Condition it starts working. I am using it as
<StackPanel Name="StackViewCount" Style="{StaticResource StackViewStyle}">
...
</StackPanel>
While looking output window i found this error
BindingExpression path error: 'FileState' property not found on 'object' ''StackPanel' (Name='StackViewCount')'. BindingExpression:Path=FileState; DataItem='StackPanel' (Name='StackViewCount'); target element is 'StackPanel' (Name='StackViewCount'); target property is 'NoTarget' (type 'Object')
So how can i tell the binding to look for FileState in UserControl not stackpanel
Now when i changed condition to
<Condition Binding="{Binding Path=FileState}" Value="Uploading" />
I dont see any errors but still it does not work.
Since FileState is property of your UserControl and it is ancestor of StackPanel you have to bind to ancestor like:
<Condition Binding="{Binding Path=FileState, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" Value="Uploading" />