I have a UserControl subclass that contains a Grid, which in turn contains a couple TextBlocks and a Border (which also contains a TextBlock). See code below.
<UserControl x:Class="ProjectNS.MyUserControl"
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"
xmlns:my="clr-namespace:ProjectNS"
mc:Ignorable="d"
Height="49" Width="150" BottomResizeLocked="True" TopResizeLocked="True"
MoveLocks="Vertical" Margin="0,-4" Focusable="True">
<my:MyUserControl.Resources>
<Style x:Key="BorderStyle" TargetType="Border">
<Setter Property="Background" Value="Blue"/>
<Setter Property="BorderBrush" Value="Blue"/>
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource
AncestorType={x:Type my:GanttBar}}, Path=IsKeyboardFocusWithin}"
Value="True">
<Setter Property="Background" Value="{StaticResource
SelectedGanttBarBackGroundBrush}"/>
<Setter Property="BorderBrush" Value="{StaticResource
SelectedGanttBarBorderBrush}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</my:MyUserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="2*" />
<RowDefinition Height="3*" />
<RowDefinition Height="2*" />
</Grid.RowDefinitions>
<Label FontSize="8.5" HorizontalAlignment="Left"
VerticalAlignment="Bottom" Margin="4,0,0,0" Foreground="Green" />
<Border Grid.Row="1" CornerRadius="5" BorderThickness="1.5" Style="
{StaticResource BorderStyle}" FocusVisualStyle="{StaticResource
SelectedBorderStyle}" Focusable="True" >
<Label FontSize="10" HorizontalAlignment="Center" FontWeight="Bold"
VerticalAlignment="Top" Foreground="White" Margin="0,2,0,0" />
</Border>
<Label HorizontalAlignment="Right" FontSize="8.5" Grid.Row="2"
VerticalAlignment="Top" Margin="0,0,4,0" Foreground="Red" />
</Grid>
</my:MyUserControl>
I'm trying to get the color of the embedded Border to change color when my UserControl receives focus, but I can't for the life of me figure out what actually receives focus when I click on the control. I've tried using the GotFocus event for every control, and nothing fires once the program is running.
Use a DataTrigger on the property IsKeyboardFocusWithin. I'm not positive the exact syntax, but it should look something like this:
<Style TargetType="{x:Type Border}">
<Setter Property="BorderBrush" Value="Red" />
<Style.Triggers>
<!-- Will change Border color when KeyboardFocus inside Border -->
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="BorderBrush" Value="Green" />
</Trigger>
<!-- Will change Border color when UserControl contains KeyboardFocus -->
<DataTrigger Binding="{Binding RelativeSource={RelativeSource
AncestorType={x:Type local:MyUserControl}},
Path=IsKeyboardFocusWithin}" Value="True">
<Setter Property="BorderBrush" Value="Blue" />
</DataTrigger>
</Style.Triggers>
</Style>
Related
Can someone please tell me how to program actually(!) resizing windows in wpf?
I searched for the solution online, pasted countless code examples, but none of them work like I want them to.
My target is to create a window, that if resized by the user, resizes everything inside, including buttons and text. The window should keep proportions and ideally have a minimum size, but this is purely optional. All solutions I found just resize the window, but not really the elements in it, at least not all. I read somewhere that Stackpanel doesn't really resize, but my tries with Grid also failed and Stackpanel seems a bit easier to arrange contents.
An example of a code I found just resizing the window, but not really the content (at least nor vertically) would be:
<Window x:Class="WPFClient.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WPFClient"
mc:Ignorable="d"
Title="MainWindow" Width="Auto" Height="Auto" SizeToContent="WidthAndHeight">
<Border Padding="10">
<StackPanel>
<!-- Server -->
<ComboBox SelectedItem="s1" Padding ="2, 2, 2, 2" Margin ="0, 0, 0, 10" MinWidth="220"/>
<!-- Username -->
<TextBox x:Name="Input_Username" Height="21" TextWrapping="Wrap" Padding="2">
<TextBox.Style>
<Style TargetType="TextBox" xmlns:sys="clr-namespace:System;assembly=mscorlib">
<Style.Resources>
<VisualBrush x:Key="CueBannerBrush" AlignmentX="Left" AlignmentY="Center" Stretch="None">
<VisualBrush.Visual>
<Label Content="Username" Foreground="LightGray" />
</VisualBrush.Visual>
</VisualBrush>
</Style.Resources>
<Style.Triggers>
<Trigger Property="Text" Value="{x:Static sys:String.Empty}">
<Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
</Trigger>
<Trigger Property="Text" Value="{x:Null}">
<Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter Property="Background" Value="White" />
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
<!-- Password -->
<TextBox x:Name="Input_Password" Height="21" TextWrapping="Wrap" Padding="2">
<TextBox.Style>
<Style TargetType="TextBox" xmlns:sys="clr-namespace:System;assembly=mscorlib">
<Style.Resources>
<VisualBrush x:Key="CueBannerBrush" AlignmentX="Left" AlignmentY="Center" Stretch="None">
<VisualBrush.Visual>
<Label Content="Password" Foreground="LightGray" />
</VisualBrush.Visual>
</VisualBrush>
</Style.Resources>
<Style.Triggers>
<Trigger Property="Text" Value="{x:Static sys:String.Empty}">
<Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
</Trigger>
<Trigger Property="Text" Value="{x:Null}">
<Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter Property="Background" Value="White" />
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<!-- Login-->
<Button x:Name="WPFLoginButton" Click="WPFLoginButton_Click" Content="Login" Grid.Column="0" Margin ="0 10 20 10" Padding="2"/>
<!-- Options-->
<Button x:Name="WPFOptionsButton" Click="WPFOptionsButton_Click" Content="Options" Grid.Column="1" Margin ="20 10 0 10" Padding="2"/>
</Grid>
<!-- Ses-->
<TextBlock Text="Ses" FontWeight="Bold"/>
<TextBox x:Name="SesField" IsReadOnly="True" Background="#eee" Padding="2" Text=""/>
</StackPanel>
</Border>
</Window>
A small example with an explanation would be enough, the above code should just demonstrate what I found but don't want.
That's pretty uncommon behavior you want to achieve. However, I think you can do it by wrraping all your controls that you want to resize, inside a Viewbox. Can't give a sample since writing this from phone.
<Window x:Class="WpfComtrolLibTest.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfComtrolLibTest"
mc:Ignorable="d"
Title="Window1" Height="450" Width="800">
<Viewbox Margin="0,0,88.2,55.8">
<Border Padding="10">
<StackPanel>
<!-- Server -->
<ComboBox SelectedItem="s1" Padding ="2, 2, 2, 2" Margin ="0, 0, 0, 10" MinWidth="220"/>
<!-- Username -->
<TextBox x:Name="Input_Username" Height="21" TextWrapping="Wrap" Padding="2">
<TextBox.Style>
<Style TargetType="TextBox" xmlns:sys="clr-namespace:System;assembly=mscorlib">
<Style.Resources>
<VisualBrush x:Key="CueBannerBrush" AlignmentX="Left" AlignmentY="Center" Stretch="None">
<VisualBrush.Visual>
<Label Content="Username" Foreground="LightGray" />
</VisualBrush.Visual>
</VisualBrush>
</Style.Resources>
<Style.Triggers>
<Trigger Property="Text" Value="{x:Static sys:String.Empty}">
<Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
</Trigger>
<Trigger Property="Text" Value="{x:Null}">
<Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter Property="Background" Value="White" />
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
<!-- Password -->
<TextBox x:Name="Input_Password" Height="21" TextWrapping="Wrap" Padding="2">
<TextBox.Style>
<Style TargetType="TextBox" xmlns:sys="clr-namespace:System;assembly=mscorlib">
<Style.Resources>
<VisualBrush x:Key="CueBannerBrush" AlignmentX="Left" AlignmentY="Center" Stretch="None">
<VisualBrush.Visual>
<Label Content="Password" Foreground="LightGray" />
</VisualBrush.Visual>
</VisualBrush>
</Style.Resources>
<Style.Triggers>
<Trigger Property="Text" Value="{x:Static sys:String.Empty}">
<Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
</Trigger>
<Trigger Property="Text" Value="{x:Null}">
<Setter Property="Background" Value="{StaticResource CueBannerBrush}" />
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter Property="Background" Value="White" />
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<!-- Login-->
<Button x:Name="WPFLoginButton" Click="WPFLoginButton_Click" Content="Login" Grid.Column="0" Margin ="0 10 20 10" Padding="2"/>
<!-- Options-->
<Button x:Name="WPFOptionsButton" Click="WPFOptionsButton_Click" Content="Options" Grid.Column="1" Margin ="20 10 0 10" Padding="2"/>
</Grid>
<!-- Ses-->
<TextBlock Text="Ses" FontWeight="Bold"/>
<TextBox x:Name="SesField" IsReadOnly="True" Background="#eee" Padding="2" Text=""/>
</StackPanel>
</Border>
</Viewbox>
</Window>
I have a parent user control which has a detail section and a tree section in it. My intention is on two toggle button i should be able to hide and show the controls.
<DockPanel>
<DockPanel DockPanel.Dock="Left">
<view:ListBoxUserControl DockPanel.Dock="Top" Visibility="{Binding IsListVisible ,Converter={StaticResource BoolToVisibilityConverter}}"/>
<view:TreeUserControl DockPanel.Dock="Top" Visibility="{Binding IsTreeVisible,Converter={StaticResource BoolToVisibilityConverter}}"/>
</StackPanel>
<view:DetailSectionUserControl/>
</StackPanel>
IsListVisible and IsTreeVisible is set based on two toggle button in the view.
so when IsListVisible is false the ListBoxUserControl will be hidden and TreeUserControl will move to top. this is working well.
But there are two problems here i face.
1) Requirement is that the both controls should be having same size. here the first tree will be created based on the items in it and rest of the space will be taken by TreeUserControl. How shall i make the size even.
2) When i add an item to ListBoxUserControl the control just grows and TreeUserControl size get reduced. How shall i get a scroll instead .
Try:
<Grid>
<Grid.RowDefinitions>
<RowDefinition>
<RowDefinition.Style>
<Style TargetType="{x:Type RowDefinition}">
<Setter Property="Height" Value="*" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsListVisible}" Value="False">
<Setter Property="Height" Value="0" />
</DataTrigger>
</Style.Triggers>
</Style>
</RowDefinition.Style>
</RowDefinition>
<RowDefinition>
<RowDefinition.Style>
<Style TargetType="{x:Type RowDefinition}">
<Setter Property="Height" Value="*" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsTreeVisible}" Value="False">
<Setter Property="Height" Value="0" />
</DataTrigger>
</Style.Triggers>
</Style>
</RowDefinition.Style>
</RowDefinition>
</Grid.RowDefinitions>
<ScrollViewer Grid.Row="0" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto">
<view:ListBoxUserControl Visibility="{Binding IsListVisible ,Converter={StaticResource BoolToVisibilityConverter}}"/>
</ScrollViewer>
<view:TreeUserControl Grid.Row="1" Visibility="{Binding IsTreeVisible,Converter={StaticResource BoolToVisibilityConverter}}"/>
</Grid>
I tried to google but all problems had related heading but problem context different. My problem is that I have a DataTrigger which gets triggered when certain property has a certain value i-e IsDockPanelVisible has true/false (different triggers for each value) in my case. Now when it gets triggered, it should set the value of Width - a property defined in ViewModel. Here is my specific code:
<Style.Triggers>
<DataTrigger Binding="{Binding IsDockPanelVisible}" Value="False">
<Setter Property="mainWindowViewModel.Width" Value="Auto">
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding IsDockPanelVisible}" Value="True">
<Setter Property="mainWindowViewModel.Width" Value="7*"></Setter>
<Setter Property="MinWidth">
<Setter.Value>
<MultiBinding Converter="{StaticResource StringSumtoIntConvert}">
<Binding ElementName="cdLblNotificationsHeader" Path="MinWidth"/>
<Binding ElementName="cdBtnNotificationsClose" Path="ActualWidth"/>
</MultiBinding>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
Here is complete code:
<Window x:Class="EmbroidaryManagementSystem_V2._0.View.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:EmbroidaryManagementSystem_V2._0.View"
xmlns:adf="clr-namespace:EmbroidaryManagementSystem_V2"
xmlns:collectionVM="clr-namespace:EmbroidaryManagementSystem_V2._0.ViewModel.CollectionsViewModel"
xmlns:helperClasses="clr-namespace:EmbroidaryManagementSystem_V2._0.HelperClasses"
xmlns:mainWindowVM="clr-namespace:EmbroidaryManagementSystem_V2._0.ViewModel.UIViewModel"
mc:Ignorable="d"
Title="Khalil Embroidery Management System" Height="655.512" Width="1135.159" FontSize="24"
WindowStartupLocation="CenterScreen" MinWidth="200" MinHeight="300"
Icon="/EmbroidaryManagementSystem V2.0;component/Images/KhalilEmbroideryLogonobackgrnd2.png"
>
<Window.DataContext>
<!--<collectionVM:ClientCollectionVM/>-->
<mainWindowVM:MainWindowViewModel/>
</Window.DataContext>
<Window.Resources>
<helperClasses:StringSumtoIntConverter x:Key="StringSumtoIntConvert"/>
<ControlTemplate x:Key="DockedPanelButtonTemplate" TargetType="{x:Type Button}">
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Black"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<Style x:Key="DockedPanelButton" TargetType="Button">
<Setter Property="LayoutTransform">
<Setter.Value>
<RotateTransform Angle="90"/>
</Setter.Value>
</Setter>
<!--<Setter Property="Template" Value="{StaticResource DockedPanelButtonTemplate}"/>-->
<Setter x:Name="border" Property="BorderBrush" Value="DodgerBlue"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="BorderBrush" Value="Aquamarine"/>
<Setter Property="Background" Value="Yellow"/>
</Trigger>
</Style.Triggers>
</Style>
<!--<mainWindowVM:MainWindowViewModel x:Key="WindowViewModel"/>-->
<Style x:Key="OnIsDockPanelVisibleChangedGridBehaviour" TargetType="Grid">
<Style.Triggers>
<DataTrigger Binding="{Binding IsDockPanelVisible}" Value="False">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsDockPanelVisible}" Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
<Style x:Key="OnIsDockPanelVisibleChangedPanelColumnBehaviour" TargetType="ColumnDefinition">
<Style.Triggers>
<DataTrigger Binding="{Binding IsDockPanelVisible}" Value="False">
<Setter Property="mainWindowViewModel.Width" Value="Auto">
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding IsDockPanelVisible}" Value="True">
<Setter Property="mainWindowViewModel.Width" Value="7*"></Setter>
<Setter Property="MinWidth">
<Setter.Value>
<MultiBinding Converter="{StaticResource StringSumtoIntConvert}">
<Binding ElementName="cdLblNotificationsHeader" Path="MinWidth"/>
<Binding ElementName="cdBtnNotificationsClose" Path="ActualWidth"/>
</MultiBinding>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
<Style x:Key="OnIsDockPanelVisibleChangedButtonBehaviour" TargetType="Button"
BasedOn="{StaticResource DockedPanelButton}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsDockPanelVisible}" Value="True">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsDockPanelVisible}" Value="False">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
<Style x:Key="OnIsDockPanelVisibleChangedGridSplitterBehaviour" TargetType="GridSplitter">
<Style.Triggers>
<DataTrigger Binding="{Binding IsDockPanelVisible}" Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsDockPanelVisible}" Value="False">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
<SolidColorBrush x:Key="TransparentBackground">
Transparent
</SolidColorBrush>
<Style x:Key="LeftDockedPanelButton" TargetType="Button" BasedOn="{StaticResource OnIsDockPanelVisibleChangedButtonBehaviour}">
<Setter Property="BorderThickness" Value="0,0,0,15"/>
</Style>
<Style x:Key="RightDockedPanelButton" TargetType="Button" BasedOn="{StaticResource OnIsDockPanelVisibleChangedButtonBehaviour}">
<Setter Property="BorderThickness" Value="0,8,0,0"/>
</Style>
<BitmapImage x:Key="LogoImage" UriSource="/Images/KhalilEmbroideryLogonobackgrnd2.png"/>
</Window.Resources>
<!--<ScrollViewer HorizontalScrollBarVisibility="Auto">-->
<Grid x:Name="mainGrid" Background="#FFD6DBE9">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition MinHeight="103"/>
</Grid.RowDefinitions>
<Menu Height="18" VerticalAlignment="Top" Grid.Row="0" Margin="0,0,0,0">
<MenuItem Header="_Exit">
<MenuItem Header="Exit"/>
</MenuItem>
<MenuItem Header="_View">
<MenuItem Header="Notifications" Command="{Binding ShowDockPanelCommand}"/>
</MenuItem>
<MenuItem Header="Add _New">
<MenuItem Header="Employee"/>
<MenuItem Header="Employee Salary"/>
</MenuItem>
<MenuItem Header="_About">
<MenuItem Header="About us"/>
</MenuItem>
</Menu>
<ScrollViewer HorizontalScrollBarVisibility="Auto" Grid.Row="1">
<Grid x:Name="innerContentGrid" MinHeight="500" MinWidth="600">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20*" MinWidth="{Binding MinWidth, ElementName=tabDataEntities}"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Style="{StaticResource OnIsDockPanelVisibleChangedPanelColumnBehaviour}" Width="{Binding }"/>
</Grid.ColumnDefinitions>
<GridSplitter x:Name="gridSplitter" Grid.Column="1" HorizontalAlignment="Center"
Width="3" Margin="0,10,0,0" Background="#FF657695"
Style="{StaticResource OnIsDockPanelVisibleChangedGridSplitterBehaviour}"/>
<Grid x:Name="gridNotificationsHeader" Grid.Column="2" Background="#FF657695" Margin="0,10,0,0"
Height="30" VerticalAlignment="Top" Style="{StaticResource OnIsDockPanelVisibleChangedGridBehaviour}">
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="cdLblNotificationsHeader"
MinWidth="{Binding Width, ElementName=lblNotificationsHeader}"/>
<ColumnDefinition x:Name="cdBtnNotificationsClose" Width="Auto"/>
</Grid.ColumnDefinitions>
<Label x:Name="lblNotificationsHeader" Content="Notifications" VerticalAlignment="Top"
FontSize="14.667" Height="29" Foreground="#FFEBF0EE" HorizontalAlignment="Left" Width="92"/>
<Button x:Name="btnNotificationsClose" Content="X"
Margin="0,5,8,0" VerticalAlignment="Top" Width="20" FontFamily="Verdana" HorizontalAlignment="Right"
Background="Transparent" FontSize="13.333" Foreground="Black" Grid.Column="1"
Command="{Binding HideDockPanelCommand}"/>
</Grid>
<TabControl Grid.Column="0" x:Name="tabDataEntities" Margin="0,10,5,0" FontSize="12"
MinWidth="{Binding ElementName=TabItemOne, Path=ActualWidth}">
<TabItem x:Name="TabItemOne">
<TabItem.Header>Tab Item</TabItem.Header>
<Grid Background="#FFE5E5E5" Margin="0,0,0,0"/>
</TabItem>
<TabItem Header="TabItem">
<Grid Background="#FFE5E5E5"/>
</TabItem>
</TabControl>
<Button x:Name="btnShowNotificationsPanel" Content="Notifications" Grid.Column="2"
Margin="0,12,-0,0" VerticalAlignment="Top" Style="{StaticResource RightDockedPanelButton}" Background="Transparent"
FontSize="12" Height="Auto" HorizontalAlignment="Right" Width="Auto"
Command="{Binding ShowDockPanelCommand}"/>
</Grid>
</ScrollViewer>
</Grid>
Width is property in my ViewModel and not FrameworkElement.Width. However, it has the same double type. ViewModel class is MainWindowViewModel and its object in XAML is mainWindowVM.
You can not set view model properties with a setter of your view.
Have a look here: Setter.Property Property.
It states that you can only uses a DependencyProperty as the value for the setter (Besides, you cannot specify a binding expression there, just a string value).
<object Property="DependencyProperty" .../>
Suggestion:
If IsDockPanelVisible is a property inside your view model, you could react to change events there in your view model, either by subscribing to INotifyPropertyChanged of this property or by calling a method in the setter of IsDockPanelVisible.
You could then set another property in your view model which is bound to the view and then achieve your desired result.
I have a scenario where I need to hide some content based on whether a radio button is checked or unchecked. For some reason I can't get this to work the way I expect it to. The behavior is the opposite of what I expect. If I adjust my xaml to accomodate the actual behavior that I'm seeing it everything gets hidden.
Essentially what I have is two radio buttons labeled Fixed and Cycle. When Fixed is checked I want the textbox associated with Fixed to have a visible foreground and the textbox associated with Cycle to have a transparent foreground and vice-versa. What I'm seeing is the exact opposite.
Here's my trigger:
<Grid.Resources>
<Style TargetType="TextBox" x:Key="FixedModeStyle">
<Setter Property="Foreground" Value="Transparent" />
<Setter Property="Width" Value="40" />
<Setter Property="Height" Value="20" />
<Setter Property="Margin" Value="10" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked,
ElementName=rbtFixedMode}" Value="True" >
<Setter Property="Foreground"
Value="{DynamicResource My.Fonts.Global.LightForeground}" />
</DataTrigger>
</Style.Triggers>
</Style>
<Style TargetType="TextBox" x:Key="CycleModeStyle">
<Setter Property="Foreground" Value="Transparent" />
<Setter Property="Width" Value="40" />
<Setter Property="Height" Value="20" />
<Setter Property="Margin" Value="10" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked,
ElementName=rbtCycleMode}" Value="True" >
<Setter Property="Foreground"
Value="{DynamicResource My.Fonts.Global.LightForeground}" />
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Resources>
Here's my radio buttons and associated textboxes:
<RadioButton x:Name="rbtFixedMode" Content="Fixed"
GroupName="AveragingMode"
Foreground="{DynamicResource My.Fonts.Global.LightForeground}"
IsChecked="{Binding AveragingWindowMode,
Converter={StaticResource EnumToBooleanConverter},
ConverterParameter={x:Static Processors:AveragingMode.Fixed}}" />
<DockPanel Grid.Row="1" IsEnabled="{Binding IsChecked, ElementName=rbtFixedMode}">
<TextBox x:Name="txtFixedIntervalLength"
Style="{StaticResource FixedModeStyle}" DockPanel.Dock="Left"
Text="{Binding AveragingWindowFixedLength}" />
</DockPanel>
<RadioButton x:Name="rbtCycleMode" Content="Cycle"
GroupName="AveragingMode" Grid.Row="2"
Foreground="{DynamicResource My.Fonts.Global.LightForeground}"
IsChecked="{Binding AveragingWindowMode,
Converter={StaticResource EnumToBooleanConverter},
ConverterParameter={x:Static Processors:AveragingMode.Cycles}}" />
<DockPanel Grid.Row="3" IsEnabled="{Binding IsChecked, ElementName=rbtCycleMode}">
<TextBox x:Name="txtCycleIntervalLength"
Style="{StaticResource CycleModeStyle}" DockPanel.Dock="Left"
Text="{Binding AveragingWindowCycleLength}"/>
<TextBlock x:Name="txbCycles" Text="Cycles" Margin="4,10"
Foreground="{DynamicResource My.Fonts.Global.LightForeground}" />
</DockPanel>
Any ideas?
Just making the text transparent is a bad idea, the user will still be able to edit it while it is transparent. Besides that the code is obfuscated and redundant. Do not create two styles for a TextBox, both containing the same setters; create a base-style and use BasedOn for sub-styles.
Not quite sure where your code goes wrong, i would suggest you clean it up, maybe there is some logical error, also here is a working example:
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib">
<Page.Resources>
</Page.Resources>
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<RadioButton Name="rbCycle" GroupName="g1" Content="Cycle"/>
<RadioButton Name="rbFixed" GroupName="g1" Content="Fixed" Grid.Column="1"/>
<TextBox Grid.Row="1" Text="cycle box">
<TextBox.Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="Visibility" Value="Hidden"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, ElementName=rbCycle}" Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
<TextBox Grid.Row="1" Grid.Column="1" Text="fixed box">
<TextBox.Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="Visibility" Value="Hidden"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, ElementName=rbFixed}" Value="True">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
</Grid>
</ScrollViewer>
</Page>
If you're using binding to set the values of your radio buttons, don't use groups. If you're using groups, don't use binding. The two don't play well together.
That may not be the cause of what you're seeing. But I bet it is. And it's certainly interfering with your ability to diagnose the problem, because after you start clicking on buttons their binding doesn't work anymore.
I have a ListBox that is bound to a list of CustomerViewModel-objects, that each has two dependency properties:
- Name (string)
- Description (string)
- IsVisible (bool)
(the IsVisible property is True by default and is reversed via the ToggleVisibility Command on the CustomerViewModel)
I would like to display the Name and Description to the right of a Border-control, that is has a Transparent background when the IsVisible property is True and Green when the False.
My problem is that the DataTrigger part of the code below doesn't work the way I want, because the Setter-part isn't triggered when the IsVisible is changed.
What am I doing wrong?
Here's my code:
<UserControl.Resources>
<Style x:Key="ListBoxStyle" TargetType="{x:Type ListBox}">
<Setter Property="Margin" Value="-1,-1,0,0" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="ItemContainerStyle" Value="{DynamicResource ListboxItemStyle}" />
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled" />
</Style>
<Style x:Key="ListboxItemStyle" TargetType="{x:Type ListBoxItem}">
<Setter Property="Background" Value="Transparent" />
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Grid>
<Border x:Name="border" Background="{TemplateBinding Background}" BorderBrush="#FFD4D6D5" BorderThickness="0,0,0,1">
<Grid Height="70" Margin="0,0,10,0">
<Grid.RowDefinitions>
<RowDefinition Height="10" />
<RowDefinition Height="Auto" />
<RowDefinition />
<RowDefinition Height="10" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Border x:Name="visibilityColumn" Grid.Row="0" Grid.Column="0" Grid.RowSpan="4" Background="Transparent" Width="4" Margin="0,0,4,0" />
<TextBlock x:Name="customerName" Grid.Row="1" Grid.Column="1" Foreground="#FF191919" FontWeight="Bold" Text="{Binding Name}" VerticalAlignment="Top" />
<TextBlock Grid.Row="2" Grid.Column="1" VerticalAlignment="Stretch" Text="{Binding Description}" TextWrapping="Wrap" Foreground="#FFB4B4B4" TextTrimming="CharacterEllipsis" />
</Grid>
<Border.ContextMenu>
<ContextMenu>
<MenuItem Header="Edit..." />
<MenuItem Header="Visible" IsCheckable="True" IsChecked="{Binding IsVisible}" Command="{Binding ToggleVisibility}"/>
</ContextMenu>
</Border.ContextMenu>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#FFEEEEEE" />
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="#FFF5F5F5" />
<Setter TargetName="customerName" Property="Foreground" Value="Green" />
</Trigger>
<DataTrigger Binding="{Binding IsVisible}" Value="False"> <!--If Value="True" the customerName Border shows up green!-->
<Setter Property="Background" Value="Green" />
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<ListBox Style="{StaticResource ListBoxStyle}" ItemsSource="{Binding CustomerViewModels}" />
UPDATED:
The DataTrigger was indeed missing the TargetName="visibilityColumn" as pointed out by Goblin.
However - the "real" problem was, this line:
<MenuItem Header="Visible" IsCheckable="True" IsChecked="{Binding IsVisible}" Command="{Binding ToggleVisibility}"/>
A checkable MenuItem has a TwoWay binding-mode on the IsChecked-property, so I was actually inverting the IsVisiblity twice - via databinding and via the ToggleVisibility command... Whoops :)
Try switching this part:
<DataTrigger Binding="{Binding IsVisible}" Value="False">
<Setter Property="Background" Value="Green" />
</DataTrigger>
With this part:
<DataTrigger Binding="{Binding IsVisible}" Value="False">
<Setter TargetName="visibilityColumn" Property="Background" Value="Green" />
</DataTrigger>
I think you missed the TargetName property in your setter. (Same goes for your IsSelected- and IsMouseOver-trigger by the way)
Hope this helps!