The property "Style" can only be set once - c#

I am trying to get this answer to work, however I get the error The property "Style" can only be set once.. Why is that?
This is what I have:
<UserControl x:Class="SFVControls.Controls.Basic.BooleanRectangleView"
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="20" d:DesignWidth="40">
<StackPanel Name="stackTextPanel" Orientation="Horizontal">
<StackPanel.Style>
<Setter Property="Margin" Value="0,8,0,0" />
<Style TargetType="{x:Type StackPanel}">
<Style.Triggers>
<DataTrigger Binding="{Binding QuickDrawBarPinned}" Value="False">
<Setter Property="Margin" Value="0,8,0,0" />
</DataTrigger>
<DataTrigger Binding="{Binding QuickDrawBarPinned}" Value="True">
<Setter Property="Margin" Value="0,48,0,0" />
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
</StackPanel>
</UserControl>

You've got two direct children of <StackPanel.Style>: A Setter for Margin that belongs within the Style, and the Style itself. You can only assign one thing to <StackPanel.Style>, and that thing has to be a Style.
So just move the Margin setter inside the Style element:
<StackPanel Name="stackTextPanel" Orientation="Horizontal">
<StackPanel.Style>
<Style TargetType="{x:Type StackPanel}">
<!-- Gotta be inside the Style, not outside. -->
<Setter Property="Margin" Value="0,8,0,0" />
<Style.Triggers>
<DataTrigger Binding="{Binding QuickDrawBarPinned}" Value="False">
<Setter Property="Margin" Value="0,8,0,0" />
</DataTrigger>
<DataTrigger Binding="{Binding QuickDrawBarPinned}" Value="True">
<Setter Property="Margin" Value="0,48,0,0" />
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
</StackPanel>
In short, your style has a fashion faux pas.

Related

Complementing Application.Resources.Style with UserControl.Style for DataRow in DataGrid

I have a global style used in all the applications DataGrid's, defined in the Application.Resources:
<Application.Resources>
<ResourceDictionary>
<Style x:Key="StyleDataGridRow" TargetType="{x:Type DataGridRow}">
<Setter Property="VerticalAlignment" Value="Center" />
<Style.Triggers>
<Trigger Property="DataGrid.IsSelected" Value="True">
<Setter Property="DataGrid.BorderBrush" Value="{DynamicResource SecondaryHueMidBrush}" />
<Setter Property="DataGrid.BorderThickness" Value="1" />
<Setter Property="Background" Value="{DynamicResource PrimaryHueLightBrush}" />
</Trigger>
<Trigger Property="DataGrid.IsSelected" Value="False">
<Setter Property="DataGrid.BorderBrush" Value="{DynamicResource SecondaryHueMidBrush}" />
<Setter Property="DataGrid.BorderThickness" Value="1" />
</Trigger>
</Style.Triggers>
</Style>
</Application:Resources>
In my UserControl I would like to add a style - keeping the global style - to highlight a row depending on an item used in this DataGrid. I could define this style in the UserControl's resources:
<UserControl.Resources>
<ResourceDictionary>
<Style x:Key="priceMissing" TargetType="{x:Type DataGridRow}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=priceIsMissing}" Value="true">
<Setter Property="Background" Value="LightSalmon" />
</DataTrigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
</UserControl.Resources>
The global style is applied to the UserControl's DataGrid like this:
<DataGrid x:Name="dgCalculatedServices"
Margin="20,0,0,0"
CellStyle="{StaticResource StyleDataGridCell}"
DataContext="{Binding}"
ItemsSource="{Binding calculationServiceCodes.collection}"
Style="{StaticResource StyleDataGrid}"
RowStyle="{StaticResource StyleDataGridRow}">
Does anyone know a way to use the global style on a DataGrid and complement it with the local style?
That is what the BasedOn property is for.
Styles can be based on other styles through this property. When you use this property, the new style will inherit the values of the original style that are not explicitly redefined in the new style.
Specify the StyleDataGridRow style as the base style for priceMissing.
<UserControl.Resources>
<ResourceDictionary>
<Style x:Key="priceMissing" TargetType="{x:Type DataGridRow}" BasedOn="{StaticResource StyleDataGridRow}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=priceIsMissing}" Value="true">
<Setter Property="Background" Value="LightSalmon" />
</DataTrigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
</UserControl.Resources>
Then use the priceMissing style in your DataGrid.
<DataGrid x:Name="dgCalculatedServices
...
RowStyle="{StaticResource priceMissing}">
You could of course rename the priceMissing style to StyleDataGridRow instead. The style would then be overwritten in the scope of the UserControl.

wpf button command binding after trigger the propery changes

i have a button in my wpf form and the button is having the image text in mvvm application when i click the button it will attach the file, my requirement is when it attached successfully the text is changed to Approve , I want to write another command propery for this command after changed the text to Approve.
<Button ToolTip="Attach Approval"
Height="25"
Command="{Binding AddAttachmentCommand}"
Margin="5,10,5,10">
<Button.Style>
<Style TargetType="{x:Type Button}">
<!-- Default Content value -->
<Setter Property="Content">
<Setter.Value>
<StackPanel Orientation="Horizontal">
<Image Source="/UILibrary;component/Themes/Default/Images/Attach.PNG"/>
</StackPanel>
</Setter.Value>
</Setter>
<!-- Triggered values -->
<Style.Triggers>
<DataTrigger Binding="{Binding IsAttachmentAvailable}" Value="True">
<Setter Property="Visibility" Value="Visible"/>
<Setter Property="Content" Value="Appprove"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsAttachmentAvailable}" Value="False">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
If you want to change a property (in your case the Command) in a trigger, you have to initialise the property in the style setter. To make your code work remove the command property from the button and add the command property to the style setter.
<Button ToolTip="Attach Approval"
Height="25"
Margin="5,10,5,10">
<Button.Style>
<Style TargetType="{x:Type Button}">
<!-- Default Content value -->
<Setter Property="Command" Value="{Binding AddAttachmentCommand}"/>
<Setter Property="Content">
<Setter.Value>
<StackPanel Orientation="Horizontal">
<Image Source="/UILibrary;component/Themes/Default/Images/Attach.PNG"/>
</StackPanel>
</Setter.Value>
</Setter>
<!-- Triggered values -->
<Style.Triggers>
<DataTrigger Binding="{Binding IsAttachmentAvailable}" Value="True">
<Setter Property="Visibility" Value="Visible"/>
<Setter Property="Content" Value="Appprove"/>
<Setter Property="Command" Value="SOME OTHER COMMAND"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsAttachmentAvailable}" Value="False">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>

Change usercontrol border on its GotFocus-event within the XAML of a WPF-Project

I have a UserControl, which contains a Grid which contains a Border:
<UserControl Focusable="True" Name="uctrlScenePanel">
<Grid MouseDown="Grid_MouseDown">
<Border BorderThickness="0" BorderBrush="Black">
</Border>
</Grid>
I now wanted to change the Border-Thickness once the usercontrol "uctrlScenePanel" got Focus, but i can't get it to work and i dont really find useful Eventtrigger-Tutorials which a can understand, because i am very new to WPF.
edit:
d.moncada's answer was very helpful! my xaml now looks like this:
<Border BorderBrush="Black">
<Border.Style>
<Style TargetType="Border">
<Setter Property="BorderThickness" Value="0" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsKeyboardFocusWithin, ElementName=uctrlScenePanel}" Value="true">
<Setter Property="BorderThickness" Value="2" />
<Setter Property="Background" Value="Green" />
</DataTrigger>
<DataTrigger Binding="{Binding IsKeyboardFocusWithin, ElementName=uctrlScenePanel}" Value="false">
<Setter Property="BorderThickness" Value="0" />
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
</Border>
I have still problems,because the focusing of a user control behaves weird, but thats another story...this one is solved for me, thanks for the lesson ;)
You can bind to the UserControl IsFocused property using a DataTrigger.
<UserControl Focusable="True" x:Name="uctrlScenePanel">
<Grid MouseDown="Grid_MouseDown">
<Border BorderBrush="Black">
<Broder.Style>
<Style TargetType="Border">
<Setter Property="BorderThickness" Value="1"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsFocused, ElementName=uctrlScenePanel}" Value="True">
<Setter Property="BorderThickness" Value="0"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
</Border>
</Grid>
</UserControl>

Cannot create an instance of "[user control]" error in designer

I have created the following user control. When I add it to a xaml window, I get the error "Cannot create an instance of "ucAppItem". I dragged the user control onto the window from the toolbar.
XAML of user control is as follows:
<UserControl x:Class="Demos.ucAppItem"
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" Width="852" Height="215">
<Grid>
<Label Name="lblTitle" Content="Title" HorizontalAlignment="Left" Margin="233,10,0,0" VerticalAlignment="Top" FontSize="22" FontFamily="Arial"/>
<Image Width="40" Height="40" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="0,0,80,0">
<Image.Style>
<Style TargetType="{x:Type Image}">
<Setter Property="Source" Value="pack://siteoforigin:,,,/arrow2.png"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Source" Value="pack://siteoforigin:,,,/arrow1.png"/>
</Trigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
<Label x:Name="lblRun" Content="Run" HorizontalAlignment="Right" Margin="0,88,35,0" VerticalAlignment="Top" Foreground="#FF2EAADC" FontSize="20">
<Label.Style>
<Style TargetType="{x:Type Label}">
<Setter Property="Foreground" Value="#FF2EAADC"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="#006d9e"/>
</Trigger>
</Style.Triggers>
</Style>
</Label.Style>
</Label>
</Grid>
</UserControl>
XAML of window is as follows:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Demos" x:Class="Demos.Window1"
Title="Window1" Height="487" Width="854">
<Grid>
<local:ucAppItem/>
</Grid>
</Window>
Thanks for your help in advance!
#Anatoily Nikolaev - thanks for your help! Your pointer on the label fixed the issue I had with it and you were right about the image. I'll mark your response as the answer. It was the source that was the issue.
My label is now defined as:
<Label x:Name="lblRun" Content="Run" HorizontalAlignment="Right" Margin="0,88,35,0" VerticalAlignment="Top" FontSize="20">
<Label.Style>
<Style TargetType="{x:Type Label}">
<Setter Property="Foreground" Value="#FF2EAADC"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="#006d9e"/>
</Trigger>
</Style.Triggers>
</Style>
</Label.Style>
</Label>
My image is now defined as:
<Image>
<Image.Style>
<Style TargetType="{x:Type Image}">
<Setter Property="Source" Value="{StaticResource arrow2}"/>
<Setter Property="Height" Value="40"/>
<Setter Property="Width" Value="40"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="Margin" Value="0,0,80,0"/>
<Setter Property="HorizontalAlignment" Value="Right"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Source" Value="{StaticResource arrow1}"/>
</Trigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
And I have resources (set in the App.xaml file), set as this:
<Application x:Class="demos.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
<BitmapImage x:Key="arrow1" UriSource="arrow1.png" />
<BitmapImage x:Key="arrow2" UriSource="arrow2.png" />
</Application.Resources>
</Application>
First, instead of pack://siteoforigin:,,,/arrow2.png need to write your actual URI and to make sure that the file exists in the project as a resource, like this (MSDN):
pack://application:,,,/arrow1.png
Secondly, trigger style for the label lblRun, will not work because you set this Foreground value locally, in WPF have a list of value precedence (MSDN), that the local value of a higher priority than the trigger style:
<Label x:Name="lblRun" Foreground="#FF2EAADC" FontSize="20" ... />
Try to remove it Foreground local value and use Style setter:
<Label x:Name="lblRun" Content="Run" HorizontalAlignment="Right" Margin="0,88,35,0" VerticalAlignment="Top" FontSize="20">
<Label.Style>
<Style TargetType="{x:Type Label}">
<Setter Property="Foreground" Value="#FF2EAADC"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="#006d9e"/>
</Trigger>
</Style.Triggers>
</Style>
</Label.Style>
</Label>

Calling a Image style

Is there any way to create a call'able image style? I have multiple buttons on a user control that have the same button and button image style. I can set the button style so that it can be called from the style (dynamic resource) of the button.
Here is an example of my code and the image style code:
<Grid.Resources>
<Style TargetType="Button"
x:Key="ButtonEditSaveStyle">
<Setter Property="IsEnabled"
Value="False" />
<Style.Triggers>
<DataTrigger Binding="{Binding CanEdit}"
Value="True">
<Setter Property="IsEnabled"
Value="True" />
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Resources>
<Button Width="32"
Height="22"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Name="gdEmployeeInfo_btnUpdateRecord"
Click="gdEmployeeInfo_btnUpdateRecord_Click"
Style="{DynamicResource ResourceKey=ButtonEditSaveStyle}"/>
I want to set my code up so that I can have the call above an have an additional call or a combined call to set the image style as well. I know I can have the image style in the button (as shown in this next code), but I want to have one place to update multiple buttons using the same style setup. Image style code:
<Image>
<Image.Style>
<Style TargetType="{x:Type Image}">
<Setter Property="Source"
Value="edit_32.png" />
<Setter Property="Stretch"
Value="Uniform" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsEditing}"
Value="True">
<Setter Property="Source"
Value="save_smallest.png" />
<Setter Property="Stretch"
Value="Uniform" />
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
Figured out the answer to my question. This set of code allows me to use dual style setting while creating only one call for the button's style:
<!--SaveEditImageSwitch-->
<Image x:Key="SaveEditImage" x:Shared="False">
<Image.Style>
<Style TargetType="{x:Type Image}">
<Setter Property="Source"
Value="edit_32.png" />
<Setter Property="Stretch"
Value="Uniform" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsEditing}"
Value="True">
<Setter Property="Source"
Value="save_smallest.png" />
<Setter Property="Stretch"
Value="Uniform" />
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
<!--ButtonEditSaveStyle-->
<Style TargetType="Button"
x:Key="ButtonEditSaveStyle">
<Setter Property="IsEnabled"
Value="False" />
<Setter Property="Content"
Value="{DynamicResource ResourceKey=SaveEditImage}" />
<Style.Triggers>
<DataTrigger Binding="{Binding CanEdit}"
Value="True">
<Setter Property="IsEnabled"
Value="True" />
</DataTrigger>
</Style.Triggers>
</Style>
<Button Width="32"
Height="22"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Name="gdEmployeeInfo_btnUpdateRecord"
Click="gdEmployeeInfo_btnUpdateRecord_Click"
Style="{DynamicResource ResourceKey=ButtonEditSaveStyle}">

Categories