Enable button when textbox is validated in WPF - c#

I'm trying to disable/enable a button when a textbox is validated.
I get the validation to work (I know that it works because it changes design).
But I can't seem to get the button to change from disabled to enabled when the textbox is validate.
Here's my code:
<AdornerDecorator>
<TextBox Width="150"
Validation.ErrorTemplate="{StaticResource ValidationErrorTemplate}"
x:Name="OrgNoTextBox">
<TextBox.Text>
<Binding Path="Customer.OrgNo" UpdateSourceTrigger="PropertyChanged" >
<Binding.ValidationRules>
<client:RegexValidationRule ValidatesOnTargetUpdated="True" Pattern="OrgNo" />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
</AdornerDecorator>
...
<Button Width="80"
Height="25"
Margin="0 0 5 0"
Command="{Binding OkCommand}"
HorizontalAlignment="Left"
IsDefault="True"
Content="Save">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="IsEnabled" Value="false" />
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding ElementName=OrgNo, Path=(Validation.HasError)}"
Value="false" />
</MultiDataTrigger.Conditions>
<Setter Property="IsEnabled"
Value="true" />
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>

Your ElementName in the MultiDataTrigger is wrong. It should be OrgNoTextBox instead of OrgNo.

like it
private void Grid_MouseMove_1(object sender, MouseEventArgs e)
{
btn.IsEnabled = false;
if (txt.IsArrangeValid == true)
{
btn.IsEnabled = true;
}
}

Related

How to disable validation of a combox element when visibility is collapsed?

I want to disable the validation of a ComboBox or a TextBox when their visibility is collapsed. Can I realize this within the XAML code?
<ComboBox Name="XYZCb" ItemsSource="{Binding XYZ}" Visibility="{Binding IsVisible, Converter={StaticResource BoolToVisibilityConverter}}">
<ComboBox.Text>
<Binding Path="xyz" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<valid:ValidationRule ValidatesOnTargetUpdated="True"/>
</Binding.ValidationRules>
</Binding>
</ComboBox.Text>
</ComboBox>
Button property binding:
<Button.IsEnabled>
<MultiBinding Converter="{StaticResource InverseAndBooleansToBooleanConverter}"
Mode="TwoWay">
<Binding ElementName="XYZCb" Path="(Validation.HasError)"/>
</MultiBinding>
<Button.IsEnabled>
If I understand correctly what you need:
<Button>
<Button.Style>
<Style TargetType="Button">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=(Validation.HasError), ElementName=XYZCb}" Value="True"/>
<Condition Binding="{Binding Visibility, ElementName=XYZCb}" Value="Visible"/>
</MultiDataTrigger.Conditions>
<Setter Property="IsEnabled" Value="False"/>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
Don't forget to remove your <Button.IsEnabled> binding.

WPF trigger validation of a content control to enable or disable a button

I have a UserControl with a ContentControl, which is a UserControl too.
This Content Control can be filled with any UserControl. I now want to lock a button in the parent UserControl, as long as the child UserControl doesn't have any errors.
Parrent:
The Content Control:
<ContentControl Name="SerializationLayerContentControl"
Grid.Row="1"
Grid.ColumnSpan="2"
Content="{Binding SerializationLayerConfiguration.ConfigView}">
</ContentControl>
and the button:
<Button Name="CreateTelegramBttn" Content="Create Telegram" Grid.Row="2" Click="CreateTelegramBttn_Click">
<Button.Style>
<Style TargetType="Button">
<Setter Property="IsEnabled" Value="False"/>
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=(Validation.HasError), ElementName=SerializationLayerContentControl}" Value="False"/>
</MultiDataTrigger.Conditions>
<Setter Property="IsEnabled" Value="True"/>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
<Button Name="CreateAndSaveTelegramBttn" Content="Create and save" Grid.Row="2" Grid.Column="1" Click="CreateAndSaveTelegramBttn_OnClick"></Button>
Child:
This is what I've got in the child UserControl
<ListBox Grid.ColumnSpan="2" Grid.RowSpan="3"
ItemsSource="{Binding FieldDefinitionElements}">
<ListBox.ItemTemplate>
<DataTemplate>
<DockPanel>
<Label>
<Label.Content>
<MultiBinding Converter="{StaticResource FieldDefConverter}">
<Binding Path="Element.FieldName"></Binding>
<Binding Path="Element.FieldType"></Binding>
<Binding Path="Element.FieldLength"></Binding>
</MultiBinding>
</Label.Content>
</Label>
<TextBox DockPanel.Dock="Right">
<TextBox.Resources>
<validation:BindingProxy Data="{Binding Path=Element}" x:Key="proxy"/>
</TextBox.Resources>
<TextBox.Text>
<Binding
Path="Value"
Mode="TwoWay"
UpdateSourceTrigger="PropertyChanged"
NotifyOnSourceUpdated="True"
NotifyOnTargetUpdated="True"
NotifyOnValidationError="True"
ValidatesOnDataErrors="True"
ValidatesOnNotifyDataErrors="True">
<Binding.ValidationRules>
<validation:FieldDefinitionElementRule ValidatesOnTargetUpdated="True">
<validation:FieldDefinitionElementRule.Wrapper>
<validation:Wrapper StringFormat="{Binding Path=Data.FieldType, Source={StaticResource proxy}}" IntFormat="{Binding Path=Data.FieldLength, Source={StaticResource proxy}}"/>
</validation:FieldDefinitionElementRule.Wrapper>
</validation:FieldDefinitionElementRule>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
</DockPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Currently it's not working that the button is locked when there are any errors.

Change image of button on click of combobox

I am trying something like this: as my form load I have one image on button (this part work fine) and one check box. When I check checkbox, the image of button should change. I have attached my xaml code with this. Please go through it and suggest changes.
<CheckBox Name="checkbox" Margin="141,148,336,147"/>
<Button Foreground="Black" Height="50" Margin="238,206,179,64">
<Button.Template>
<ControlTemplate TargetType="{x:Type Button}">
<StackPanel Orientation="Horizontal">
<Image>
<Image.Style>
<Style>
<Setter Property="Image.Source"
Value="Images/cancel_16.ico" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=checkbox, Path=IsChecked,
RelativeSource={RelativeSource AncestorType=
{x:Type Button}}}" Value="True">
<Setter Property="Image.Source"
Value="Images/cancel_16grayscale.ico" />
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
<ContentPresenter Content="{TemplateBinding Content}"
Margin="5,0,0,0" />
</StackPanel>
</ControlTemplate>
</Button.Template>
</Button>
Just Remove the RelativeSource and add UpdateSourceTrigger Like this in your style
<Image.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=checkbox, Path=IsChecked,UpdateSourceTrigger=PropertyChanged}"
Value="True">
<Setter Property="Image.Source"
Value="Back_jeans.jpg" />
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=checkbox, Path=IsChecked,UpdateSourceTrigger=PropertyChanged}"
Value="False">
<Setter Property="Image.Source"
Value="Blue_Front_Jeans.jpg" />
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>

How to make a WPF listbox item not clickable

I am using a listbox to display a list of items that I am selecting programmatically in a voice activated program. Is there any way to keep the selected item from being clicked on? I do want mouse over functionality, just not clicking on the actual item.
I have tried to set Focusable (does not do anything for what I want) and IsEnabled (disables mouse over)
Here is my current style:
<Style x:Key="GlyphList" TargetType="ListBox">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" IsEnabled="False"/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemTemplate">
<Setter.Value>
<DataTemplate DataType="models:SpellingGlyph">
<Label VerticalAlignment="Bottom">
<Label.Template>
<ControlTemplate>
<Grid>
<TextBlock Name="MainText" Text="{Binding Text}" VerticalAlignment="Bottom" Margin="0,0,5,0"/>
</Grid>
<ControlTemplate.Triggers>
<DataTrigger Value="True">
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource ObjectReferenceEqualityConverter}">
<Binding />
<Binding Path="SelectedItem" RelativeSource="{RelativeSource FindAncestor, AncestorType=ListBox}"/>
</MultiBinding>
</DataTrigger.Binding>
<Setter TargetName="MainText" Property="Foreground" Value="#75BAFF"/>
<Setter TargetName="MainText" Property="FontWeight" Value="SemiBold"/>
<Setter TargetName="MainText" Property="FontSize" Value="22"/>
</DataTrigger>
<DataTrigger Value="True">
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource MultiBooleanConverter}"> <!--SelectedItem trumps mouse over-->
<Binding ElementName="MainText" Path="IsMouseOver"/>
<Binding Path="SelectedItem" RelativeSource="{RelativeSource FindAncestor, AncestorType=ListBox}" Converter="{StaticResource InvertedNullCheckToBooleanConverter}"/>
</MultiBinding>
</DataTrigger.Binding>
<Setter TargetName="MainText" Property="Foreground" Value="#75BAFF"/>
<Setter TargetName="MainText" Property="FontWeight" Value="SemiBold"/>
<Setter TargetName="MainText" Property="FontSize" Value="22"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Label.Template>
</Label>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
<ListBox PreviewMouseDown="ListBox_OnPreviewMouseDown"..
private void ListBox_OnPreviewMouseDown(object sender, MouseButtonEventArgs e)
{
e.Handled = true;
}
An alternative solution to what I accepted was to add the following in my view model:
if (_viewModelSetSelectedGlyph != value) return;
_selectedGlyph = value;
OnPropertyChanged("SelectedGlyph");
Then, set the _viewModelSetSelectedGlyph each time before actually setting the SelectedGlyph. Then, when the UI tries to set the SelectedGlyph, it would not succeed, only when the view model sets it by also setting the private variable does it succeed.
Simply set IsHitTestVisible to false
https://msdn.microsoft.com/en-us/library/system.windows.uielement.ishittestvisible(v=vs.110).aspx

Change Label content with IsMouseOver on checkbox

Hei,
Im creating a button what has a checkbox on top of it. Now when user hovers over the checkbox with a mouse i would like to change the text on the button.
Here's what i have currently:
<Button Grid.Row="1" Margin="0,0,136,12" Name="btnRefresh" Height="28" VerticalAlignment="Bottom" HorizontalAlignment="Right" Width="120" Click="btnRefresh_Click">
<Grid Width="111">
<CheckBox Height="16" HorizontalAlignment="Left" Margin="0,2,0,0" Name="cbAutoRefresh" VerticalContentAlignment="Center">
<CheckBox.Style>
<Style TargetType="{x:Type CheckBox}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Content" Value="Auto Refresh" />
</Trigger>
</Style.Triggers>
</Style>
</CheckBox.Style>
</CheckBox>
<Label Name="btnLabel" Margin="32,-4,25,-4">Refresh</Label>
</Grid>
</Button>
But like this it changes the content of the checkbox, how can i change the btnLabel content?
Currently you're just modifing the style of the ComboBox, thats why the Trigger just changes the Content of your ComboBox.
To listen to other controls properties in a Trigger, you can use Databinding like so:
<Label Name="btnLabel" Margin="32,-4,25,-4">
<Label.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=comboBoxName, Path=IsMouseOver}" Value="False"
<Setter Property="Content" Value="Refresh"/>
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=comboBoxName, Path=IsMouseOver}" Value="True"
<Setter Property="Content" Value="Auto Refresh"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Label.Style>
</Label>

Categories