Reputation: 115
There are TextBox and Button controls in WPF:
<TextBox Name="BackUpTextBox" />
<Button Name="BackUpSave" Content="Save" />
Button BackUpSave must be enabled if a text of BackUpTextBox is changed. I know how to do that by BackUpTextBox TextChanged event by C# code. But is there a way to enable/disable button by XAML notation?
Upvotes: 0
Views: 5459
Reputation: 81233
You can achieve that via EventTrigger
. Wrap both controls in StackPanel
so that TextChanged
events routed upto its parent StackPanel.
And in that case enable Button by setting IsEnabled
to True
.
<StackPanel>
<TextBox x:Name="BackUpTextBox"/>
<Button x:Name="BackUpSave" Content="Save" IsEnabled="False"/>
<StackPanel.Triggers>
<EventTrigger RoutedEvent="TextBox.TextChanged">
<BeginStoryboard>
<Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="IsEnabled"
Storyboard.TargetName="BackUpSave">
<DiscreteBooleanKeyFrame KeyTime="0:0:0" Value="True"/>
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="IsEnabled"
Storyboard.TargetName="BackUpSave">
<DiscreteBooleanKeyFrame KeyTime="0:0:0" Value="False"/>
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="Loaded">
<BeginStoryboard>
<Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="IsEnabled"
Storyboard.TargetName="BackUpSave">
<DiscreteBooleanKeyFrame KeyTime="0:0:0" Value="False"/>
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</StackPanel.Triggers>
</StackPanel>
UPDATE
In case you want to disable button on button click again, add another event handler for Button.Click
and set it to disable from that. I have updated the xaml code for that.
UPDATE 2
Solution looks such cumbersome that I have big doubt if it worth compared to just setting IsEnabled property in Initial, TextChanged and Click events. Am I missed something that XAML style more preferable these days?
Yes, i have to agree with that XAML only solutions are sometimes cumbersome which can easily be done using code behind. Specifically in your case it could have been done simply by hooking onto some events and more importantly that's not violating any MVVM rules since you are doing view specific things in code behind. So, i see no harm in doing ti from code behind.
XAML only solutions i would generally prefer in cases where i want to store my XAML loosely in some text file and want to load that at runtime using XamlReader.Load()
.
And as i mentioned animation has higher precedence over local values setter for Dependency property. So, once TextChanged
event gets raised value gets set to true and any further change to that property from code behind won't work.
But anyhow you can change that from code behind by setting it via animation (will post here just for completeness of answer and might help others who stumble upon this post). This is how you do it from code behind:
private void Button_BackUpSave_Click(object sender, RoutedEventArgs e)
{
EnableDisableBackUpSaveButton(false);
}
private void EnableDisableBackUpSaveButton(bool value)
{
BooleanAnimationUsingKeyFrames animation =
new BooleanAnimationUsingKeyFrames();
DiscreteBooleanKeyFrame keyFrame = new DiscreteBooleanKeyFrame(value,
KeyTime.FromTimeSpan(TimeSpan.FromMilliseconds(0)));
animation.KeyFrames.Add(keyFrame);
BackUpSave.BeginAnimation(Button.IsEnabledProperty, animation);
}
Now, in XAML you can only have single XAML trigger on TextChanged
.
Upvotes: 3
Reputation: 16119
You can use a data trigger:
<TextBox Name="BackUpTextBox" />
<Button Name="BackUpSave" Content="Save">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="IsEnabled" Value="True" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=BackUpTextBox, Path=Text, UpdateSourceTrigger=PropertyChanged, Mode=OneWay}" Value="{x:Null}">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=BackUpTextBox, Path=Text, UpdateSourceTrigger=PropertyChanged, Mode=OneWay}" Value="">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
In a real-world application though you wouldn't do this in XAML because there'd be no way to test this behavior in your unit tests.
Upvotes: 2