Style control within control on Trigger - c#

I have a LabeledTextBox in my WPF app that's as simple as can be:
<Grid x:Name="root">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0"
Text="{Binding Label}"
FontWeight="Bold"
VerticalAlignment="Bottom"
Margin="5,2,5,0"/>
<TextBox Grid.Row="1"
Text="{Binding Text}"
VerticalAlignment="Top"
Margin="5,0,5,2"/>
</Grid>
I bind all my models to that guy to display. I've successfully implemented IDataErrorInfo, and can style the LabeledTextBox like:
<Style TargetType="controls:LabeledTextBox">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="BorderBrush" Value="Red"/>
<Setter Property="BorderThickness" Value="5"/>
</Trigger>
</Style.Triggers>
</Style>
This all works, and the entire control is bordered in red (obviously). What's I'd like is to just manipulate the TextBox within the LabeledTextBox, my end goal being to change the background to a pastel red color.
How can I access my TextBox from within the trigger, when the trigger is set on the entire LabeledTextbox?
I imagine this is a seemingly simple task, I just can't get the syntax right. I'm working in a .NET4.0 environment, if that is relevant.
Thanks!

Hi I dont think we can access elements through styles but yes we can refer through ControlTemplate.Triggers and specifying the TargetName Property in Setter.
<Style TargetType="{x:Type wpfApplication4:LabelledTextBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type wpfApplication4:LabelledTextBox}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock
Grid.Row="0"
Margin="5,2,5,0"
VerticalAlignment="Bottom"
FontWeight="Bold"
Text="ergergergegr" />
<TextBox
x:Name="MyTextBox"
Grid.Row="1"
Margin="5,0,5,2"
VerticalAlignment="Top"
Text="gtwererggerg" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter TargetName="MyTextBox" Property="BorderBrush" Value="Red"/>
<Setter TargetName="MyTextBox" Property="BorderThickness" Value="5"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Add a dependency property to your user control.
Bind Your TextBlock Background property to that dependency property.
Change that property in the trigger.

Related

WPF Custom Template button with rounded corners not responding sometimes

Im currently working on a UI with WPF embedded in a ElementHost Control(Winform) for a powerpoint add-in. The appearance for the button works fine, however sometimes when entering the button it simply doesn't respond, meaning that hover/press events are not fired and when I click on it selects the parent behind it (probaly since nothing is selected) as if the button was a ghost. When i remove the border inside the template that displays the rounded rectangle the problem dissapears, a default button also doesnt suffer from the same problem. However if the custom button has focus on it, it works flawlessly. So far my best guess is performance related issues.
Grid inside usercontrol that holds the buttons:
<Viewbox Grid.Column="2" Grid.RowSpan="3" HorizontalAlignment="Right" Margin="0,5,10,5">
<Grid Height="100" Width="100">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Button Grid.Row="0" Grid.Column="0" Background="red" Style="{StaticResource AnchorPoint}" Click="Button_Click_1"/>
<!--<Button Grid.Row="0" Grid.Column="1" Style="{StaticResource AnchorPoint}"/>
<Button Grid.Row="0" Grid.Column="2" Style="{StaticResource AnchorPoint}"/>
<Button Grid.Row="1" Grid.Column="2" Style="{StaticResource AnchorPoint}"/>
<Button Grid.Row="1" Grid.Column="1" Style="{StaticResource AnchorPoint}"/>
<Button Grid.Row="1" Grid.Column="0" Style="{StaticResource AnchorPoint}"/>
<Button Grid.Row="2" Grid.Column="0" Style="{StaticResource AnchorPoint}"/>
<Button Grid.Row="2" Grid.Column="1" Style="{StaticResource AnchorPoint}"/>-->
<Button Grid.Row="2" Grid.Column="2" Style="{StaticResource AnchorPoint}"/>
<Button Content="Button" Grid.Column="2" Grid.Row="1"/>
</Grid>
</Viewbox>
Style for button:
<Style TargetType="Button" x:Key="AnchorPoint">
<Setter Property="Background" Value="Transparent"></Setter>
<Setter Property="Foreground" Value="Transparent"></Setter>
<Setter Property="BorderBrush" Value="{x:Null}"></Setter>
<Setter Property="BorderThickness" Value="0"></Setter>
<Setter Property="HorizontalAlignment" Value="Stretch"></Setter>
<Setter Property="VerticalAlignment" Value="Stretch"></Setter>
<Setter Property="Margin" Value="0,0,0,0"></Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border x:Name="border" CornerRadius="2" Margin="0" BorderThickness="2" Style="{StaticResource TestHidden}">
<ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center" ContentSource="Content"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" Value="Red" TargetName="border"></Setter>
</Trigger>
<Trigger Property="IsFocused" Value="True">
<Setter Property="Background" Value="blue" TargetName="border"></Setter>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="green" TargetName="border"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Style for Border:
<Style x:Key="TestHidden" TargetType="Border">
<Setter Property="BorderBrush" Value="{StaticResource SkyGrey}"/>
<Setter Property="Background" Value="{x:Null}" />
<Setter Property="Focusable" Value="False"></Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="BorderBrush" Value="{StaticResource SkyGrey}" />
<Setter Property="Background" Value="{StaticResource SkyGreyHover}" />
</Trigger>
</Style.Triggers>
</Style>
My hunch is that the problem is related to setting the Background Property of the Border (Key="TestHidden") default to {x:Null}. Although it seems odd, setting the Background to null for a UIElement can cause the element to be invisible to mouse events. This is probably why the element behind the border is the one capturing mouse events instead - making the border seem like a "Ghost". Set the borders default background to Transparent.
<Style x:Key="TestHidden" TargetType="Border">
<Setter Property="BorderBrush" Value="{StaticResource SkyGrey}"/>
<Setter Property="Background" Value="Transparent" />
You might ask why parent button (Key="AnchorPoint") is not capturing mouse events instead: Although the Buttons Background is correctly set to Transparent, this property is being ignored by WPF because it is not referenced in the ControlTemplate via TemplateBinding. If you want the buttons background property to actually show up in the control, use a TemplateBinding on the control responsible for displaying the Background color (the border):
<Border x:Name="border"
CornerRadius="2"
Margin="0"
BorderThickness="2"
Style="{StaticResource TestHidden}"
Background="{TemplateBinding Background}">
<ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center" ContentSource="Content"/>
</Border>
Note: There are various other occurrences in your XAML where the issues described above might exist. Hope this helps.

TextBox validation sets Button border to red

I have an ItemsControl where I dynamically create a new GroupBox with several controls in it and model behind. That works so far. I've also implemented validation to my TextBoxes, which is also working as intended. And there is a Button to remove this GroupBox, which binds to the Ancestor of type UserControl.
<ItemsControl Grid.Row="2" ItemsSource="{Binding StorageLocationList, Mode=TwoWay}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<GroupBox Style="{StaticResource GroupBoxBase}">
<GroupBox.Header>
<CheckBox x:Name="ExportGroupCheckBox" Content="Storage Location active" IsChecked="{Binding GroupActive, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource CheckBoxBase}" IsEnabled="{Binding ElementName=ActivateExportCheckBox, Path=IsChecked}"/>
</GroupBox.Header>
<Grid>
<Grid IsEnabled="{Binding ElementName=ExportGroupCheckBox, Path=IsChecked}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Content="Name:" VerticalAlignment="Center"/>
<TextBox Grid.Row="0" Grid.Column="1" Style="{StaticResource LimitedCharTextBox}" Text="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnNotifyDataErrors=True}"/>
<Label Grid.Row="1" Grid.Column="0" Content="Storage Location:" VerticalAlignment="Center"/>
<TextBox Grid.Row="1" Grid.Column="1" IsReadOnly="True" Style="{StaticResource BaseTextBox}" Text="{Binding StorageLocationPath, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnNotifyDataErrors=True}"/>
<Button Grid.Row="1" Grid.Column="2" Content="Browse..." VerticalAlignment="Stretch" Command="{Binding StorageLocationBrowseCommand}" Style="{StaticResource ButtonBase}"/>
</Grid>
<Canvas>
<Button Canvas.Top="0" Canvas.Right="0" Content="X" ToolTip="Remove Group" Style="{StaticResource RemoveButton}" Command="{Binding ElementName=GPUserControl, Path=DataContext.RemoveStorageLocationGroupCommand}" CommandParameter="{Binding}"/>
</Canvas>
</Grid>
</GroupBox>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
When I now type something wrong in the TextBox that is bound to the Name property, the validation takes place and the TextBox receives a red border to indicate that. Cool. But the button to remove this GroupBox also gets a red border. And that's weird.
I also tried to set the Validation.ErrorTemplate of the Button to null like so:
<Setter Property="Validation.ErrorTemplate" Value="{x:Null}"/>
but that sets the TextBox Validation.ErrorTemplate to null as well.
So how are they connected to each other? Somehow through the UserControl?
Here is a screenshot of it:
EDIT:
Here are the Styles:
<Style x:Key="BaseTextBox" TargetType="TextBox">
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="TextWrapping" Value="NoWrap"/>
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Validation.ErrorTemplate" Value="{x:Null}"/>
</Trigger>
<Trigger Property="IsReadOnly" Value="True">
<Setter Property="Background" Value="LightGray"/>
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="GroupBoxBase" TargetType="GroupBox">
<Setter Property="Padding" Value="2"/>
</Style>
<Style x:Key="ConfigurationMainWindownButton" TargetType="Button">
<Setter Property="Height" Value="Auto"/>
<Setter Property="Width" Value="70"/>
<Setter Property="Margin" Value="2,2,2,2"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
</Style>
<Style x:Key="RemoveButton" TargetType="Button" BasedOn="{StaticResource ConfigurationMainWindownButton}">
<Setter Property="VerticalAlignment" Value="Top"/>
<Setter Property="HorizontalAlignment" Value="Right"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="Width" Value="20"/>
<Setter Property="Height" Value="20"/>
<Setter Property="Foreground" Value="Red"/>
<Setter Property="FontWeight" Value="Bold"/>
<!-- <Setter Property="Validation.ErrorTemplate" Value="{x:Null}"/> -->
</Style>
WPF marks all your ItemsControl as not valid not only your text box inside due to using the same data model (actually model is not valid - not controls) . Text box just set state to invalid value. You could resolve it with overriding Validation.ErrorTemplate style setting for Remove Group button control if the button have to ignore validate state of model .
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<AdornedElementPlaceholder />
</ControlTemplate>
</Setter.Value>
</Setter>

Style grid layout cover controls

I'm trying set backcolor for all grid layout in my project using resource dictionary. This is code of file where i modify my grid.
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Theme">
<SolidColorBrush x:Key="GridBackColor" Color="Red"/>
<Style TargetType="Grid">
<Setter Property="Background" Value="{StaticResource GridBackColor}"/>
<Setter Property="Opacity" Value="0.5"/>
</Style>
</ResourceDictionary>
After set Background property all controls on grid were disappear, but when i set opacity i can only say that all controls are under grid layout and any mouse events not work.
Here how it's look like:
this is my window code.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10*"/>
<ColumnDefinition Width="125"/>
<ColumnDefinition Width="20"/>
<ColumnDefinition Width="125"/>
<ColumnDefinition Width="10*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="10*"/>
<RowDefinition Height="40"/>
<RowDefinition Height="40"/>
<RowDefinition Height="20"/>
<RowDefinition Height="30"/>
<RowDefinition Height="10*"/>
</Grid.RowDefinitions>
<Label Content="Name" Grid.Column="1" Grid.Row="1" Grid.ColumnSpan="3" FontSize="20"
HorizontalAlignment="Stretch" VerticalAlignment="Center"/>
<TextBox Name="TbName" Grid.Column="1" Grid.Row="2" Grid.ColumnSpan="3" FontSize="20"
HorizontalAlignment="Stretch" />
<Button Content="Add" Name="BtAdd" Grid.Column="1" Grid.Row="4" IsDefault="True"
HorizontalAlignment="Right" VerticalAlignment="Center" Width="100" Click="BtAdd_Click"/>
<Button Content="Close" Name="BtClose" Grid.Column="3" Grid.Row="4" IsCancel="True"
HorizontalAlignment="Left" Width="100" Click="BtClose_Click"/>
</Grid>
When you applied you style globally to all the Grids in your application, the ones used inside other controls will also be affected. For instance take a look at the Window control (from the vs designer, left click on the window > Edit Template > Edit a copy)
<Window.Resources>
<ControlTemplate x:Key="WindowTemplateKey" TargetType="{x:Type Window}">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}">
<Grid>
<AdornerDecorator>
<ContentPresenter/>
</AdornerDecorator>
<ResizeGrip x:Name="WindowResizeGrip" HorizontalAlignment="Right" IsTabStop="false" Visibility="Collapsed" VerticalAlignment="Bottom"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="ResizeMode" Value="CanResizeWithGrip"/>
<Condition Property="WindowState" Value="Normal"/>
</MultiTrigger.Conditions>
<Setter Property="Visibility" TargetName="WindowResizeGrip" Value="Visible"/>
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<Style x:Key="WindowStyle1" TargetType="{x:Type Window}">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}"/>
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Window}">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}">
<AdornerDecorator>
<ContentPresenter/>
</AdornerDecorator>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="ResizeMode" Value="CanResizeWithGrip">
<Setter Property="Template" Value="{StaticResource WindowTemplateKey}"/>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
Notice the Grid defined in the Border inside the ControlTemplate.
An easy fix to your issue is to assign a key to your style and assign it to the Grid manually:
<Style TargetType="Grid" x:Key="GridStyle">
<Setter Property="Background" Value="{StaticResource GridBackColor}"/>
<Setter Property="Opacity" Value="0.5"/>
</Style>
To use it:
<Grid Style="{StaticResource GridStyle}">
...
</Grid>

WPF Databinding in ControlTemplate not working C#

I try to bind a simple bool to a checkbox and a datatrigger in a controltemplate, but nothing is working. The checkbox is only for test purpose. I already went through the posts here, but most problems are caused by setting a property directly and not in the style, thus overwriting it. The datatrigger using the mouseover property is working just fine. Its only the binding to the bool which doesn't work.
My Code so far:
cs:
public partial class HostFrame : UserControl
{
public bool test { get; set; }
public HostFrame()
{
test = true;
InitializeComponent();
}
}
Xaml:
<UserControl x:Class="OwnDrawingv2.Elements.HostFrame"
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:local="clr-namespace:OwnDrawingv2.Elements"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
<Style TargetType="{x:Type local:HostFrame}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:HostFrame}">
<Grid Background="LightBlue" Name="host_grid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition Width="Auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="20"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<ContentPresenter Name="content" Grid.Row="1" Grid.Column="1" />
<CheckBox Grid.Column="0" Grid.Row="0" IsChecked="{Binding Path=test}"> <!--Test prupose-->
</CheckBox>
<Image Grid.Column="1" Grid.Row="0" Name="attention" Width="30" Height="30" Source="/attention_icon.png">
<Image.Style>
<Style TargetType="Image">
<Setter Property="Visibility" Value="Visible"></Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=test}" Value="true">
<Setter Property="Visibility" Value="Hidden"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
<Ellipse Grid.Column="0" Grid.Row="1" Width="10" Height="10" Fill="Black">
<Ellipse.Style>
<Style TargetType="Ellipse">
<Setter Property="Visibility" Value="Hidden"></Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=content, Path=IsMouseOver}" Value="true">
<Setter Property="Visibility" Value="Visible"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Ellipse.Style>
</Ellipse>
<Ellipse Grid.Column="2" Grid.Row="1" Width="10" Height="10" Fill="Black">
<Ellipse.Style>
<Style TargetType="Ellipse">
<Setter Property="Visibility" Value="Hidden"></Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=content, Path=IsMouseOver}" Value="true">
<Setter Property="Visibility" Value="Visible"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Ellipse.Style>
</Ellipse>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
</UserControl>
UPDATE: I got an answer for my original question and I understand this. But why are there tutorials in the web, which seem to work without the relativesource?
UPDATE2: I missed one answers information about Datacontext, thank you. The problem is solved.
You have not set a Datacontext for your UserControl therefore i assume it will be null. You should see the binding error in your output.
On the other hand, your property test doesnt't notify changes. You should declare it as a dependency property if it belongs to the UserControl (instead of being part of the ViewModel)
if you do the following IsChecked="{Binding Path=test}" that means your UserControl class is the DataContext of it self (or you didn't say that).
So you have 2 solutions (I guess)
1- Move your Test property to your ViewModel and do your Binding.
2- Use RelativeResource and FindAncestor method ({Binding Path=PathToProperty, RelativeSource={RelativeSource AncestorType={x:Type typeOfAncestor}}})
PS: IF your HostFrame inherits from Control,UIELement..., It would be better to define a DependencyProperty and do a TemplateBinding

Landscape-Portrait orientation in WPF

I am new to WPF and working on dynamic view creation. I have a scenario where i need to modify my UI based on monitor landscape and/or portrait, like
I already have property which tells me that monitor is in landscape or portrait mode.
Is this possible in WPF?
This is possible. You would create a view that implements both layouts and switches between them using a DataTrigger:
<ContentControl>
<ContentControl.Style>
<Style TargetType="ContentControl">
<Setter Property="Content">
<Setter.Value>
<!-- Put your portrait layout here -->
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding IsLandscape}" Value="True">
<Setter Property="Content">
<Setter.Value>
<!-- Put your landscape layout here -->
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
Using the {Binding IsLandscape} expression, the DataTrigger observes the IsLandscape property of the view's DataContext. This is explained in detail on MSDN. This means that you should set the view's DataContext property to the object that has the IsLandscape property that you've mentioned in your question. Full example:
Create new empty WPF project.
Update your MainWindow.xaml.cs:
public MainWindow()
{
this.InitializeComponent();
this.DataContext = this; // You would put a ViewModel here when using MVVM design pattern
}
public static readonly DependencyProperty IsLandscapeProperty
= DependencyProperty.Register("IsLandscape",
typeof (bool),
typeof (MainWindow));
public bool IsLandscape
{
get { return (bool) GetValue(IsLandscapeProperty); }
set { SetValue(IsLandscapeProperty, value); }
}
private void ChangeOrientation(object sender, RoutedEventArgs e)
{
this.IsLandscape = !this.IsLandscape;
}
Update your MainWindow.xaml. Delete the default Grid and put this instead:
<Window.Resources>
<Style TargetType="UserControl">
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Background" Value="#CCDDEE" />
<Setter Property="Margin" Value="3" />
</Style>
</Window.Resources>
<DockPanel>
<Button DockPanel.Dock="Bottom" Margin="5" Content="Change Orientation"
Click="ChangeOrientation" />
<ContentControl>
<ContentControl.Style>
<Style TargetType="ContentControl">
<Setter Property="Content">
<Setter.Value>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<UserControl Content="Sub 1" />
<UserControl Grid.Column="1" Content="Sub 2" />
<UserControl Grid.Row="1" Grid.ColumnSpan="2" Content="Main" />
</Grid>
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding IsLandscape}" Value="True">
<Setter Property="Content">
<Setter.Value>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<UserControl Grid.Column="1" Content="Sub 1" />
<UserControl Grid.Column="1" Grid.Row="1" Content="Sub 2" />
<UserControl Grid.RowSpan="2" Content="Main" />
</Grid>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
</DockPanel>
Yes, you can implement both of this UI and use VisualStateManager to control which UI to display.
Also you can bind visibility of layout container to your property using converter

Categories