I am relatively new in MVVM. May i know is that a way i can get the element in my user control and bind it separately in a ContentTemplate? I draft a sample code like below.
I have a user control consists of RedStack, GreenStack, BlueStack. My goal is if condition A then show the RedStack and BlueStack in the ContentTemplate, else show all color stacks in the ContentTemplate
Color user control :
<UserControl x:Class="MapDisplay.ColorView"
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="300" d:DesignWidth="300">
<StackPanel>
<StackPanel x:Name="RedStack">
<Rectangle Fill="Red" Width="100" Height="100"/>
</StackPanel>
<StackPanel x:Name="GreenStack" >
<Rectangle Fill="Green" Width="100" Height="100"/>
</StackPanel>
<StackPanel x:Name="BlueStack" >
<Rectangle Fill="Blue" Width="100" Height="100"/>
</StackPanel>
</StackPanel>
Main user control:
<UserControl x:Class="WpfApplication.UserControl"
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:custom="clr-namespace:MapDisplay;assembly=MapDisplay"
xmlns:Controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
mc:Ignorable="d" >
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary>
<DataTemplate DataType="{x:Type custom:ColorController}">
<custom:ColorView/>
</DataTemplate>
<DataTemplate x:Key="ColorDisplay">
<Controls:MetroAnimatedSingleRowTabControl ItemsSource="{Binding Colors}" />
</DataTemplate>
<ControlTemplate x:Key="SplitColorDisplay">
<StackPanel>
<ContentControl Content="{Binding}"
ContentTemplate="{StaticResource ColorDisplay.Colors.RedStack?}" />
<ContentControl Content="{Binding}"
ContentTemplate="{StaticResource ColorDisplay.Colors.BlueStack?}" />
</StackPanel>
</ControlTemplate>
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Border>
<ContentControl DockPanel.Dock="Top" Content="{Binding}">
<ContentControl.Style>
<Style TargetType="ContentControl">
<Setter Property="ContentTemplate" Value="{StaticResource ColorDisplay}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsSplitColor}" Value="True">
<Setter Property="Template" Value="{StaticResource SplitColorDisplay}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
</Border>
</UserControl>
Related
The following code does not make the window I run invisible. What am I missing? Initially, my goal was to bind the visibility of the window to the Model View's WindowVisibility Boolean property but when that wouldn't work, I removed the conditional triggering and just assigned a style that set it to collapsed but it still doesn't work.
<Window x:Class="WindowWalker.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Width="1000" MinHeight="10" Height="85" ResizeMode="NoResize" Topmost="True" WindowStyle="None" Loaded="Window_Loaded" WindowStartupLocation="CenterScreen" SizeToContent="Height">
<Window.Style>
<Style TargetType="{x:Type Window}">
<Setter Property="Visibility" Value="Collapsed"/>
<!--<Style.Triggers>
<DataTrigger Binding="{Binding WindowVisibility}" Value="True">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>-->
</Style>
</Window.Style>
<Window.Resources>
<ResourceDictionary>
<VisualBrush x:Key="SettingsBrush" Visual="{StaticResource appbar_settings}"/>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Resources/Icons.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
<StackPanel Orientation="Vertical">
<TextBox Text="{Binding SearchText, UpdateSourceTrigger=PropertyChanged}" FontSize="40" Margin="10" KeyUp="SearchBoxKeyUp"/>
<ListBox x:Name="results" ItemsSource="{Binding Results}" SelectedItem="{Binding SelectedWindowResult}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding ResultWindow.Title}"></TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</Grid>
</Window>
I created a new WPF project by Blend 2017 (.net 4.7) with one window and this Xaml (added no code behind):
<Window x:Class="WpfApp1.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:WpfApp1"
mc:Ignorable="d"
Title="MainWindow"
Height="350"
Width="525">
<Window.Resources>
<Style x:Key="_borderStyleWithChildBinding"
TargetType="{x:Type Border}"
BasedOn="{StaticResource {x:Type Border}}">
<Setter Property="BorderBrush"
Value="{Binding RelativeSource={RelativeSource Self}, Path=Child.Fill}" />
</Style>
</Window.Resources>
<Grid Width="50"
Height="30"
Margin="10">
<Border BorderThickness="5"
Style="{StaticResource _borderStyleWithChildBinding}">
<Border.Child>
<Rectangle Width="20"
Height="10"
Fill="Green" />
</Border.Child>
</Border>
</Grid>
</Window>
It compiles but reports a runtime error concerning line
BasedOn="{StaticResource {x:Type Border}}"
Exception: System.Windows.Markup.XamlParseException: A value for System.Windows.Markup.StaticResourceHolder caused an exception.
InnerException: Resource System.Windows.Controls.Border cannot be found.
The designer is smart enough to show the right thing:
We can solve the problem by omitting the x:Key and the BasedOn property of the border style:
<Window x:Class="WpfApp1.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:WpfApp1"
mc:Ignorable="d"
Title="MainWindow"
Height="350"
Width="525">
<Window.Resources>
<Style TargetType="{x:Type Border}" >
<Setter Property="BorderBrush"
Value="{Binding RelativeSource={RelativeSource Self}, Path=Child.Fill}" />
</Style>
</Window.Resources>
<Grid Width="50"
Height="30"
Margin="10">
<Border BorderThickness="5">
<Border.Child>
<Rectangle Width="20"
Height="10"
Fill="Green" />
</Border.Child>
</Border>
</Grid>
</Window>
I have an exceed data grid and I want to bind context menu property of column header.
Here is my code
<UserControl
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:xcdg="http://schemas.xceed.com/wpf/xaml/datagrid" x:Class="Sedan.Ux.Sheets.Views.SheetView"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="VisibilityConverter"/>
<Style TargetType="{x:Type xcdg:ColumnManagerCell}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type xcdg:ColumnManagerCell}">
<Grid VerticalAlignment="Center" HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{TemplateBinding Content}" HorizontalAlignment="Stretch"/>
<TextBlock Grid.Column="1" Text=" ▼" HorizontalAlignment="Stretch" >
</TextBlock>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu DataContext="{Binding Menus}" ItemsSource="{Binding Menus}">
<ContextMenu.ItemContainerStyle>
<Style TargetType="MenuItem">
<Setter Property="Header" Value="{Binding Name}"/>
<Setter Property="ItemsSource" Value="{Binding SubMenus}"/>
<Setter Property="Command" Value="{Binding Command}"/>
<Setter Property="CommandParameter" Value="{Binding Name}"></Setter>
</Style>
</ContextMenu.ItemContainerStyle>
</ContextMenu>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid>
<xcdg:DataGridControl Grid.Row="0" x:Name="Sheet" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="3" AutoCreateColumns="True" ReadOnly="{Binding ReadOnly}" ItemsSource="{Binding Data}" SelectionMode="Single" SelectedItem="{Binding SelectedItem}">
</xcdg:DataGridControl>
</Grid>
</UserControl>
I am not able to bind Menus property when I am using Setter in style.
If I remove the binding and hard code menu items ,I am able to see the context menu.
I have done research on how to get it done and I found various suggestions on stackoverflow and other forums regarding using 'Relative Source Self' in binding but that didnt work for me.
If I bind Menus to context menu of any button in user control (not via style) , then I am able to see menu.
Please help.
The style for TextBlock (below) has no effect on the DataTemplate's TextBlock. If I change TextBlock to TextBox in both the style and template, the style applies as I would expect. Why does TextBlock ignore the style?
Thank you,
Ben
<UserControl x:Class="SilverlightApplication1.MainPage"
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:l="clr-namespace:SilverlightApplication1" mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<UserControl.Resources>
<Style TargetType="TextBlock">
<Setter Property="FontSize" Value="20" />
</Style>
<Style TargetType="TextBox">
<Setter Property="FontSize" Value="20" />
</Style>
<DataTemplate DataType="l:MyObject">
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</UserControl.Resources>
<StackPanel>
<ItemsControl>
<ItemsControl.Items>
<l:MyObject Name="Frank" />
</ItemsControl.Items>
</ItemsControl>
</StackPanel>
</UserControl>
I'm trying to understand how styles works in silverlight, this is what I've done :
<UserControl x:Class="SilverlightApplication1.MainPage"
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:vm="clr-namespace:SilverlightApplication1" mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<UserControl.DataContext>
<vm:ViewModel />
</UserControl.DataContext>
<UserControl.Resources>
<Style x:Key="TestStyle" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Image Source="test.png" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<StackPanel x:Name="LayoutRoot" Background="White">
<TextBlock Text="{Binding SayHello}" />
<Button Style="{StaticResource TestStyle}" Width="100" Height="100 />
</StackPanel>
The text and the image are displayed correctly, note that test.png is a resource file at the root of my projet.
First thing I don't understand : why is my image correctly displayed at runtime, but not at design in visual studio ?
Then, I would like to use a databinded value in my style, so I use :
<UserControl x:Class="SilverlightApplication1.MainPage"
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:vm="clr-namespace:SilverlightApplication1" mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<UserControl.DataContext>
<vm:ViewModel />
</UserControl.DataContext>
<UserControl.Resources>
<Style x:Key="TestStyle" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Image Source="{Binding MyUrl}" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<StackPanel x:Name="LayoutRoot" Background="White">
<TextBlock Text="{Binding SayHello}" />
<Button Style="{StaticResource TestStyle}" Width="100" Height="100" />
</StackPanel>
Ok, it's working, my viewmodel exposes an Uri with the test.png as relative.
What I would like to do now is to use the button with many images, so it could have been great to be able to do something like this :
<UserControl x:Class="SilverlightApplication1.MainPage"
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:vm="clr-namespace:SilverlightApplication1" mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<UserControl.DataContext>
<vm:ViewModel />
</UserControl.DataContext>
<UserControl.Resources>
<Style x:Key="TestStyle" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Image Source="{TemplateBinding TheUrl}" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<StackPanel x:Name="LayoutRoot" Background="White">
<TextBlock Text="{Binding SayHello}" />
<Button Style="{StaticResource TestStyle}" Width="100" Height="100" TheUrl="{Binding MyUrl}" />
</StackPanel>
but the property TheUrl of course doesn't exists in the button.
I don't want to create my own control, the purpose is to understand styles.
How can I do this ?
Thanks in advance for any help.
Best regards
you are correct in your observation that button does not have a TheUrl property. You have to options here. One is to use the Tag property of Button:
<UserControl.Resources>
<Style x:Key="TestStyle" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Image Source="{TemplateBinding Tag}" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<StackPanel x:Name="LayoutRoot" Background="White">
<TextBlock Text="{Binding SayHello}" />
<Button Style="{StaticResource TestStyle}" Width="100" Height="100" Tag="{Binding MyUrl}" />
</StackPanel>
As an aside, I would not bind to the Width / Height properties, these may not be set explicitly. Instead, bind to ActualHeight and ActualWidth which you can guarantee will always be set.
Tag is a property of type object which can be used for general extensibility. The other, more elegant option is to define an attached property. See the tutorial in the following blog post:
http://www.hardcodet.net/2009/01/create-wpf-image-button-through-attached-properties