Hi i am trying to put what i am doing in the events from Code Behind in Triggers of a Style who is being applied in a TextBox. What i want is to prevent using the Code Behind to do that and use Triggers. Is there any way to accomplish this?
My Textbox
<TextBox Name="myTextBox" Style="{StaticResource txtBoxStyle}"/>
My style
<Style x:Key="txtBoxStyle" TargetType="{x:Type TextBox}">
<Setter Property="Foreground" Value="Silver"/>
<Setter Property="MaxLength" Value="6"/>
</Style>
The Events from Code Behind
private void myTextBox_LostFocus(object sender, RoutedEventArgs e)
{
if (myTextBox.Text.Length == 0)
myTextBox.Text = "000000";
}
private void myTextBox_GotFocus(object sender, RoutedEventArgs e)
{
if (myTextBox.Text == "000000")
myTextBox.Clear();
}
private void myTextBox_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (!(e.Key >= Key.D0 && e.Key <= Key.D9) && e.Key != Key.Back)
e.Handled = true;
}
private void myTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
if (myTextBox.Text == "000000")
myTextBox.Foreground = Brushes.Silver;
else
{
myTextBox.Foreground = Brushes.Black;
if(myTextBox.Text.Length == 6)
myButton.Visibility = Visibility.Visible;
else
myButton.Visibility = Visibility.Hidden;
}
}
Thanks in advance!
Edit: Using triggers for this logic is not a good idea and will in all likelihood fail because of its self-referencing (causes a stack-overflow), value converters are also a bit problematic. To encapsulate complex logic and apply it via a Style use an attached behavior.
<Style TargetType="{x:Type TextBox}">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding IsFocused, RelativeSource={RelativeSource Self}}" Value="False"/>
<Condition Binding="{Binding Text, RelativeSource={RelativeSource Self}}" Value=""/>
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
<Setter Property="Text" Value="000000"/>
</MultiDataTrigger.Setters>
</MultiDataTrigger>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding IsFocused, RelativeSource={RelativeSource Self}}" Value="True"/>
<Condition Binding="{Binding Text, RelativeSource={RelativeSource Self}}" Value="000000"/>
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
<Setter Property="Text" Value=""/>
</MultiDataTrigger.Setters>
</MultiDataTrigger>
<Trigger Property="Text" Value="000000">
<Setter Property="Foreground" Value="Silver"/>
</Trigger>
</Style.Triggers>
<!-- If (Text != "000000") Foreground = Brushes.Black -->
<Setter Property="Foreground" Value="Black"/>
</Style>
The logic which sets the visibility of the button should not be handled in this style but by the button. The key-down event cannot be translated.
Button style:
<Style TargetType="{x:Type Button}">
<Setter Property="Visibility" Value="Hidden"/> <!-- Normal state -->
<Style.Triggers>
<DataTrigger Binding="{Binding Text.Length, ElementName=myButton}" Value="6">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
Related
I have a simple DataGrid with the following column:
<DataGridTextColumn Header="Column" Binding="{Binding ColumnValue, Mode=TwoWay, UpdateSourceTrigger=LostFocus}">
<DataGridTextColumn.CellStyle>
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="IsEnabled" Value="{Binding IsColumnEnabled}" />
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background" Value="Gray" />
<Setter Property="Foreground" Value="Transparent" />
</Trigger>
</Style.Triggers>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
Let's assume two rows, the second one is disabled. When I enter a value into the first cell and hit Enter, the focus doesn't jump to the next cell (because it's disabled). The problem is, I cannot enter into edit mode again with doubleclick until the current cell is focused.
Is there any trick to avoid this?
If you want to implement a custom behaviour for Enter key presses, you could override the OnKeyDown method in a custom class:
public class CustomDataGrid : DataGrid
{
protected override void OnKeyDown(KeyEventArgs e)
{
if(e.Key == Key.Return)
{
var currentCell = CurrentCell;
base.OnKeyDown(e);
if (CurrentCell.Column.GetCellContent(CurrentCell.Item)?.Parent is DataGridCell cell && !cell.IsEnabled)
CurrentCell = currentCell;
}
else
{
base.OnKeyDown(e);
}
}
}
Don't forget to change the root element of the DataGrid in your XAML:
<local:CustomerDataGrid ... />
I have write this code to change the color of a cell in WPF mydatagrid, but as result i have all the row colored and i don't know why.
Style style = this.FindResource("backColor") as Style;
DataGridClientFile.CellStyle = style;
<Style x:Key="backColor" TargetType="DataGridCell">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=Colore}" Value="Red">
<Setter Property="Background" Value="Red"/>
<Setter Property="Foreground" Value="White"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=Colore}" Value="Green">
<Setter Property="Background" Value="Green"/>
<Setter Property="Foreground" Value="White"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=Colore}" Value="Yellow">
<Setter Property="Background" Value="Yellow"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=Colore}" Value="Cyan">
<Setter Property="Background" Value="Cyan"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=Colore}" Value="White">
<Setter Property="Background" Value="White"/>
</DataTrigger>
</Style.Triggers>
</Style>
Here the solution :
Style style = this.FindResource("backColor") as Style;
Style styleNX = this.FindResource("backColorNX") as Style;
if (DataGridClientFile.Columns.Count >= 14)
{
DataGridColumn col = DataGridClientFile.Columns[14];
col.CellStyle = style;
DataGridColumn colNX = DataGridClientFile.Columns[15];
colNX.CellStyle = styleNX;
}
This question already has answers here:
How do I make a textbox visible and hidden with a checkbox?
(3 answers)
Closed 4 years ago.
I have 3 CheckBoxes and I want to disable/enable two of them when the other one is checked/unchecked. The first step works (if I check checkBoxcaja, the other two checkBoxes are disabled well, but when I uncheck checkBoxcaja, the other two checkBoxes don't return to their original Enabled state.
What am I doing wrong?
I'm a newbie in WPF.
This is the code:
private void checkBoxcaja_Checked(object sender, RoutedEventArgs e)
{
if (checkBoxcaja.IsChecked == true)
{
checkBoxbanderola.IsEnabled = false;
checkBoxletra.IsEnabled = false;
}
else if (checkBoxcaja.IsChecked == false)
{
checkBoxbanderola.IsEnabled = true;
checkBoxletra.IsEnabled = true;
}
}
Thanks in advance
I'm taking a guess here and say you connected this to the Checked event.
Well, that's only fired if the box is checked. There is an Unchecked event that is fired when it is unchecked so you need to connect to that as well. Half you method belongs there.
private void checkBoxcaja_Checked(object sender, RoutedEventArgs e)
{
checkBoxbanderola.IsEnabled = false;
checkBoxletra.IsEnabled = false;
}
private void checkBoxcaja_Unchecked(object sender, RoutedEventArgs e)
{
checkBoxbanderola.IsEnabled = true;
checkBoxletra.IsEnabled = true;
}
Don't forget to hook them up. Alternatively, you can use the same event handler for both.
You can also do this completely in XAML with Datatriggers:
<CheckBox x:Name="CBOne" Grid.Column="1" Grid.Row="3" Content="One" HorizontalAlignment="Center" VerticalAlignment="Center"></CheckBox>
<CheckBox x:Name="CBTwo" Grid.Column="2" Grid.Row="3" Content="Two" HorizontalAlignment="Left" VerticalAlignment="Center">
<CheckBox.Style>
<Style TargetType="CheckBox">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=CBOne, Path=IsChecked}" Value="True">
<Setter Property="IsEnabled" Value="False"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=CBOne, Path=IsChecked}" Value="False">
<Setter Property="IsEnabled" Value="True"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</CheckBox.Style>
</CheckBox>
<CheckBox x:Name="CBThree" Grid.Column="2" Grid.Row="3" Content="Three" HorizontalAlignment="Right" VerticalAlignment="Center">
<CheckBox.Style>
<Style TargetType="CheckBox">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=CBOne, Path=IsChecked}" Value="True">
<Setter Property="IsEnabled" Value="False"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=CBOne, Path=IsChecked}" Value="False">
<Setter Property="IsEnabled" Value="True"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</CheckBox.Style>
</CheckBox>
In WPF I have this code for disabling a menuitem on a certain condition:
private void gridListPlayers_ContextMenuOpening(object sender, ContextMenuEventArgs e)
{
Player player = (Player)gridListPlayers.SelectedItem;
if(player.Owner.GUID == Guid.Empty.ToString())
{
propMenuItem.IsEnabled = false;
}
else
{
propMenuItem.IsEnabled = true;
}
}
I'm trying to achieve the same result of that function via XAML. Is there a simple way to do that?
You can set the visibility on or off according to a property in your selected Item. So create read only property ToggleMenuVisible, which returns (Owner.GUID != Guid.Empty.ToString()) and then in your xaml do something like:
<MenuItem x:Name="MyToggleMenu" Header="My Toggle Menu" >
<MenuItem.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding SelectedItem.ToggleMenuVisible}" Value="False">
<Setter Property="UIElement.Visibility" Value="Collapsed" />
</DataTrigger>
<DataTrigger Binding="{Binding SelectedItem.ToggleMenuVisible}" Value="True">
<Setter Property="UIElement.Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</MenuItem.Style>
</MenuItem>
Obviously you will need to include SelectedItem in your view's model.
I have a search box which i am trying to to check if it is empty by using the "hasdata" and if empty return false else return true, but the DataTrigger Binding is not working. can someone point me in the right direction on what i am doing wrong.
code:
public bool hasdata
{
get { if (searchBox.Text.Count() == 0) return false; else return true; }
}
xaml:
<telerik:RadWatermarkTextBox x:Name="searchBox"/>
<Image Source="SomeImage.png" >
<Image.Style>
<Style TargetType="{x:Type Image}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=hasdata}" Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=hasdata}" Value="False">
<Setter Property="Visibility" Value="Hidden"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
The UI has currently no way of being notified when hasdata is changed. You need to either implement the INotifyPropertyChanged interface or make hasdata a DependencyProperty.