I am trying to set the selected value of a combobox from a style trigger.It works as long as we dont manually change any value in the combobox.But it stops working altogether after manually changing the selection.How can i solve this.A sample code is attached.Please do help
<Window x:Class="InputGesture.Window2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:InputGesture"
Title="Window2" Height="300" Width="300" Name="Sample">
<Window.Resources>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="ComboBox.SelectedValue" Value="1"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=chk,Path=IsChecked}" Value="True">
<Setter Property="ComboBox.IsEnabled" Value="False"/>
<Setter Property="ComboBox.SelectedValue" Value="2"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<StackPanel>
<CheckBox Name="chk" Height="23"/>
<ComboBox Name="cmb" Height="23" DisplayMemberPath="Name"
SelectedValuePath="Id" ItemsSource="{Binding ElementName=Sample,Path=DT}">
</ComboBox>
<Button Height="23" Click="Button_Click"/>
</StackPanel>
</Window>
I have found a Quick but Dirty Solutuin i guess..If anyone has a better Idea Please..
<Window x:Class="InputGesture.Window2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:InputGesture"
Title="Window2" Height="300" Width="300" Name="Sample">
<Window.Resources>
<Style TargetType="{x:Type ComboBox}">
<Style.Resources>
<Storyboard x:Key="valueStoryBoard" >
<ObjectAnimationUsingKeyFrames Duration="00:00:00"
FillBehavior="HoldEnd"
Storyboard.TargetProperty="SelectedValue">
<DiscreteObjectKeyFrame KeyTime="00:00:00"
Value="{x:Null}" />
<!--<DiscreteObjectKeyFrame KeyTime="00:00:00"
Value="2" />-->
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</Style.Resources>
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, ElementName=chk}"
Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard x:Name="stb" Storyboard="{StaticResource valueStoryBoard}" />
</DataTrigger.EnterActions>
<Setter Property="ComboBox.IsEnabled" Value="False"/>
<DataTrigger.ExitActions>
<StopStoryboard BeginStoryboardName="stb" />
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<StackPanel>
<CheckBox Name="chk" Height="23"/>
<ComboBox Name="cmb" Height="23" DisplayMemberPath="Name"
SelectedValuePath="Id" ItemsSource="{Binding ElementName=Sample,Path=DT}">
</ComboBox>
<Button Height="23" Click="Button_Click"/>
</StackPanel>
</Window>
Related
<Window.Resources>
<Style TargetType="ListBoxItem">
<Style.Triggers>
<EventTrigger RoutedEvent="PreviewGotKeyboardFocus">
<BeginStoryboard>
<Storyboard>
<BooleanAnimationUsingKeyFrames
Storyboard.TargetProperty="(ListBoxItem.IsSelected)">
<DiscreteBooleanKeyFrame KeyTime="0" Value="True"/>
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Opacity" Value="1.0" />
</Trigger>
</Style.Triggers>
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}"
Color="Blue"/>
</Style.Resources>
<Setter Property="Background" Value="Red" />
<Setter Property="MaxHeight" Value="75" />
</Style>
<DataTemplate x:Key="dtTeamInGame">
<WrapPanel >
<TextBox x:Name="txtPath" Text="{Binding Path = Number, Mode=TwoWay}" MinWidth="35" ></TextBox>
<TextBox x:Name="txtPath2" Text="{Binding Path = KnownName, Mode=TwoWay}" MinWidth="125" ></TextBox>
</WrapPanel>
</DataTemplate>
</Window.Resources>
<Grid>
<ListBox x:Name="listBox" ItemTemplate="{DynamicResource dtTeamInGame}" HorizontalAlignment="Left" Height="100" Margin="29,184,0,0" VerticalAlignment="Top" Width="381">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<EventSetter Event="PreviewMouseLeftButtonDown" Handler="ListViewItem_PreviewMouseLeftButtonDownHome" />
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
<Button x:Name="button" Content="Button" HorizontalAlignment="Left" Margin="335,108,0,0" VerticalAlignment="Top" Width="75" Click="button_Click"/>
</Grid>
I have a Listbox which contains Textboxes in the item and I would like for when I click the textbox the item the textbox is in should be selected. Before adding:
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<EventSetter Event="PreviewMouseLeftButtonDown" Handler="ListViewItem_PreviewMouseLeftButtonDownHome" />
</Style>
</ListBox.ItemContainerStyle>
the list box item would be selected if I clicked the textbox within an item. If I remove the container style above it works as intended but I need the container style because I would like to carry out some tasks if the user clicks an item that is already selected.
It sounds like you want to keep behavior from the default ListBoxItem style, but you also want to add your own stuff to it. That's easy: Use the BasedOn property of the style to inherit from the existing default style.
<ListBox.ItemContainerStyle>
<Style
TargetType="ListBoxItem"
BasedOn="{StaticResource {x:Type ListBoxItem}}"
>
<!-- Your stuff -->
I have the following template defined. The TextBlock PART_TextBlock binds correctly if outside of the StackPanel but when placed inside the StackPanel I get a binding error. The StackPanel datacontext is bound to a converter and is applying the storyboard (flashing tab) as required. I need the tab to flash and also the text to display in the tab header with the flashing in the background of the text.
<dashboard:EditableTabHeaderControl.Template>
<ControlTemplate TargetType="{x:Type dashboard:EditableTabHeaderControl}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<StackPanel DataContext="{Binding Path=., Mode=OneWay, Converter={StaticResource DependencyObjectToFilterConverter}}" Grid.Row="1" Background="Transparent" >
<StackPanel.Style>
<Style TargetType="{x:Type StackPanel}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=HasError}" Value="True" >
<DataTrigger.EnterActions>
<BeginStoryboard Name="StartBlinking" >
<Storyboard>
<ColorAnimation
Storyboard.TargetProperty="Background.Color"
To="Red"
Duration="00:00:00.4"
RepeatBehavior="Forever"
AutoReverse="True" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
<DataTrigger Binding="{Binding Path=HasError}" Value="False" >
<DataTrigger.EnterActions>
<RemoveStoryboard BeginStoryboardName="StartBlinking" />
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
<TextBlock Text=" " VerticalAlignment="Top">
</TextBlock>
<TextBox x:Name="PART_TabHeader" Text="{Binding Path=Title,
Mode=TwoWay, diag:PresentationTraceSources.TraceLevel=High}" Visibility="Collapsed">
</TextBox>
<TextBlock x:Name="PART_TextBlock" Text="{Binding Path=Title,
Mode=TwoWay, diag:PresentationTraceSources.TraceLevel=High}" >
</TextBlock>
</StackPanel>
<!-- IF THE TEXBOX/TEXTBLOCK ARE PLACED HERE TITLE BINDS CORRECTLY-->
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsInEditMode" Value="True">
<Trigger.Setters>
<Setter TargetName="PART_TabHeader" Property="Visibility" Value="Visible"/>
<Setter TargetName="PART_TextBlock" Property="Visibility" Value="Collapsed"/>
</Trigger.Setters>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</dashboard:EditableTabHeaderControl.Template>
</dashboard:EditableTabHeaderControl>
I finally figured out the Binding expression, the following worked
Text="{Binding DataContext.Title, RelativeSource={RelativeSource AncestorType=dashboard:EditableTabHeaderControl}}"
After reading several SO posts (here, here, and here) I still can't find any way to solve my problem... Basically, I redefined Button layout, and packed it up in a style. The new Button ControlTemplate contains a Rectangle I want to animate on Button click. Which TargetProperty do I have to use in my animation? Following is what I done :
UserControl x:Class="OfficeTourismeBrantome.Views.MainMenuView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="800" d:DesignWidth="300">
<UserControl.Resources>
<Style x:Key="MenuItemButtonStyle" TargetType="Button">
<Setter Property="FontSize" Value="35" />
<Setter Property="FontFamily" Value="Segoe" />
<Setter Property="Foreground" Value="#FFEBEDEA" />
<!--<Setter Property="Height" Value="{Binding MenuLayout.MenuItemSize.Height}" />-->
<Setter Property="HorizontalContentAlignment" Value="Right" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Canvas HorizontalAlignment="Stretch">
<ContentPresenter Canvas.Left="{Binding MenuLayout.MenuItemLeftMargin}" HorizontalAlignment="Center"
VerticalAlignment="Center"/>
<Rectangle
Name="test"
Width="0"
Height="3"
Fill="Aqua"/>
</Canvas>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
<!-- Which targetProperty should I use to animate ControlTemplate Rectangle ?-->
From="0.0"
To="10.0"
Duration="0:0:2" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
</Style>
</UserControl.Resources>
<ItemsControl Name="menuButtonContainer" ItemsSource="{Binding Items}" Margin="{Binding MenuLayout.MenuMargin}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button
Style="{StaticResource ResourceKey=MenuItemButtonStyle}"
Margin="{Binding ElementName=menuButtonContainer,
Path=DataContext.MenuLayout.MenuItemMargin}"
Height="{Binding ElementName=menuButtonContainer,
Path=DataContext.MenuLayout.MenuItemSize.Height}"
Content="{Binding Text}"
Command="{Binding ElementName=menuButtonContainer,
Path=DataContext.ChangeThemeCommand}"
CommandParameter="{Binding Id}"
/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
I may be wrong in my implementation, still trying to understand WPF subtilities... What's the best way to achieve my goal?
Many thanks for your answers !
Which target property you want to animate is the question you have to ask yourself ! Do you want to change the rectangle's Width ? Its Opacity ? ...
Best practice... I don't know, but that's one way to do it :
<ControlTemplate TargetType="Button">
[...]
<ControlTemplate.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard TargetName="test" TargetProperty="Width">
<DoubleAnimation From="0.0" To="10.0" Duration="0:0:2" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</ControlTemplate.Triggers>
I have a ListBox with an ItemTemplate (shown below) that when the mouse is over an item, a button is displayed that will fire a Delete Command.
This works, but what I'd like is for the button to "fade in" after the mouse has been over the listitem for a couple of seconds. How can I achieve this?
<ListBox.ItemTemplate>
<DataTemplate d:DesignSource="{d:DesignInstance quizCompanion:Question}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="40"></ColumnDefinition>
<ColumnDefinition Width="16"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Path=Number}"></TextBlock>
<Button
Content="x" Grid.Column="1"
Command=MyDeleteCommand>
<Button.Style>
<Style TargetType="Button">
<Setter Property="Visibility" Value="Hidden"></Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type ListBoxItem}},Path=IsMouseOver}" Value="True">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
Try using a DataTrigger with a RelativeSource for the Binding.
Here's a sample ... mouse over anywhere on the StackPanel for 2 seconds or more and the hidden button will fade in. It'll disappear when the mouse is moved off. Hopefully it'll work within your ListBox ItemTemplate:
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<StackPanel Height="100" Background="Yellow">
<TextBlock Text="Mouse over the yellow area to see the button"/>
<Button Width="250" Height="50" HorizontalAlignment="Left" Opacity="0">
<Button.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsMouseOver, RelativeSource={RelativeSource AncestorType={x:Type StackPanel}}}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard Name="Fade">
<Storyboard>
<DoubleAnimationUsingKeyFrames Duration="0:0:3" Storyboard.TargetProperty="Opacity">
<LinearDoubleKeyFrame KeyTime="0:0:2" Value="0"/>
<LinearDoubleKeyFrame KeyTime="0:0:3" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<StopStoryboard BeginStoryboardName="Fade"/>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</StackPanel>
</Grid>
</Page>
I have added a DataTemplate to a ListBox class to bind my collection to:
<ListBox x:Name="lstEmails" Height="259" Margin="12,0,12,41" Width="276"
SelectionChanged="lstEmails_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Label Visibility="Hidden" Content="{Binding ID}"></Label>
<TextBox Width="200" Text="{Binding EmailAddress}"></TextBox>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
This does exactly what I want it to do. Although when I click on the TextBox, the ListBox does not automatically set the associated ListItem as Selected. I could do this in code, but I would prefer to use this as a component (no surprises there then).
Any ideas on how to achieve this?
That doesn't seem to work, it won't let me click on anything. Have I missed something. Here is my new XAML.
<UserControl.Resources>
<!--<TextBox x:Key="TB" x:Name="TextBoxInsideListBoxItemTemplate">
<TextBox.Style>-->
<Style TargetType="{x:Type TextBox}">
<Setter Property="IsHitTestVisible" Value="False" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type ListBoxItem}, AncestorLevel=1}}"
Value="True">
<Setter Property="IsHitTestVisible" Value="True" />
</DataTrigger>
</Style.Triggers>
</Style>
<!--</TextBox.Style>
</TextBox>-->
</UserControl.Resources>
<Grid>
<ListBox x:Name="lstEmails" Height="259" Margin="12,0,12,41" Width="276" SelectionChanged="lstEmails_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<!--<Label Visibility="Hidden" Content="{Binding ID}"></Label>-->
<TextBox Width="220" Text="{Binding EmailAddress}" >
</TextBox>
<!--<TextBox Width="220" Text="{Binding EmailAddress}" GotFocus="TextBox_GotFocus"></TextBox>-->
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button Width="20" Margin="12,0,0,12" Name="btnAdd" VerticalAlignment="Bottom" Click="btnAdd_Click" Height="23" HorizontalAlignment="Left">+</Button>
<Button Width="20" HorizontalAlignment="Left" Margin="30,0,0,12" Name="btnRemove" VerticalAlignment="Bottom" Click="btnRemove_Click" Height="23">-</Button>
<Button Height="23" HorizontalAlignment="Right" Margin="0,0,12,12" Name="btnApply" VerticalAlignment="Bottom" Width="49" Click="btnApply_Click">Apply</Button>
</Grid>
I think the click twice bit is good functionality.
You can trigger on the property IsKeyboardFocusWithin in the ItemContainerStyle and set IsSelected to true.
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsKeyboardFocusWithin, RelativeSource={RelativeSource Self}}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="(ListBoxItem.IsSelected)">
<DiscreteBooleanKeyFrame KeyTime="0" Value="True"/>
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
You could also use a Setter instead of a single frame animation but then the selection will be lost again once the focus leaves the ListBox:
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsKeyboardFocusWithin, RelativeSource={RelativeSource Self}}" Value="True">
<Setter Property="IsSelected" Value="True"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
If you have multiple instance of ListBox then you may consider using your custom listbox (by deriving it from ListBox). See the explanation here.
Or, use this hack if you have only 1 (or only small number of) such ListBox and don't want to create a separate class for that:
<TextBox x:Name="TextBoxInsideListBoxItemTemplate" ... >
<TextBox.Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="IsHitTestVisible" Value="False" />
<Style.Triggers>
<DataTrigger
Binding="{Binding IsSelected, RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type ListBoxItem}, AncestorLevel=1}}"
Value="True">
<Setter Property="IsHitTestVisible" Value="True" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
Note that you'll have to click once again to edit text in the TextBox (which is actually cool according to me).
I had a situation where the selection of a listbox item would change its layout, so the control might have moved away from the cursor before the mouse button is released. I have found no better solution than to use a slight delay in the Storyboard if I want to keep everything in xaml.
More importantly, GotKeyboardFocus seems to work better than IsKeyboardFocusWithin for repeated selections.
<EventTrigger RoutedEvent="GotKeyboardFocus">
<BeginStoryboard>
<Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="IsSelected">
<DiscreteBooleanKeyFrame KeyTime="00:00:00.3" Value="True"/>
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>