Binding styles from ResourceDictionary to usercontrols - wpf

I'm new to wpf so I'm looking for a solution and an explanation of why my attempted solution is not working.
Here's my case.
I have several UserControls. In each of them I apply the following style:
<UserControl.Resources>
<Style TargetType="TextBox" BasedOn="{StaticResource Centratura}">
<Setter Property="IsEnabled" Value="{Binding Property1.IsAbilitato}" />
</Style>
</UserControl.Resources>
based on a style defined in a resource dictionary. And it works fine.
But note that for every UserControl, the previous code is identical, except for the binding property, that will be Property1.IsAbilitato, Property2.IsAbilitato, Property3.IsAbilitato...
But this is a code duplication I don't like. I was wondering how to put the style in the resource dictionary and apply the proper binding later in each usercontrol.
I tried using the Tag property like what was suggested here, in this way:
In my user control:
<UserControl x:Class="whatever"
...
Tag="{Binding Property1.IsAbilitato}"
...>
and in the resourcedictionary:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="TextBox">
<Setter Property="IsEnabled" Value="{Binding Path=Tag, RelativeSource={RelativeSource Self}}" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
</Style>
</ResourceDictionary>
but it doesn't work. Suggestions? Other solutions? (I'm using MVVM, if it's relevant).
Thanks in advance.

You have to add the Tag to the TextBox itself:
<TextBox Tag="{Binding Property1.IsAbilitato}"/>
if you want the following to work:
<Setter Property="IsEnabled" Value="{Binding Path=Tag, RelativeSource={RelativeSource Self}}" />
But if you want to add it to the UserControl and want all TextBox's to be applied to then you have to change it to:
<Setter Property="IsEnabled" Value="{Binding Path=Tag, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl}}" />

Related

XAML separate binding of ContainerStyle and ContentTemplate in ListBox

I tried this for a while now and searched in the web without success... Now I dare to ask on stackoverflow myself.
So, the aim is to separate the definitions of the ItemContainerStyle and the ContentTemplate of a ListBoxItem. I have defined the ListBoxItemStyle in a ResourceDictionary and two different DataTemplates in the Window.Resources.
I now like to set the style of the ListBoxItem according to the one defined in the ResourceDictionary and change the DataTemplate with a trigger (IsMouseOver).
My (not working) Code so fare looks like this:
<ListBox HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="20,60,10,10"
Grid.Row="1" Grid.Column="0"
PreviewMouseMove="DragMove_PreviewMouseMove"
PreviewMouseLeftButtonDown="Drag_PreviewMouseLeftButtonDown"
ItemsSource="{Binding Persons}" VerticalContentAlignment="Center"
Style="{StaticResource DefaultListBoxStyle}">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Style" Value="{StaticResource DefaultListBoxItemStyle}"/>
<Setter Property="ContentTemplate" Value="{StaticResource PersonsListBoxItemTemplate_default}"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="ContentTemplate" Value="{StaticResource PersonsListBoxItemTemplate_infoButtons}"/>
</Trigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
where DefaultListBoxStyle is the style defined in the ResourceDictionary and PersonsListBoxItemTemplate_default & PersonsListBoxItemTemplate_infoButtons are the DataTemplates defined in the Window.Resources.
Now I get an error, that the style-object must not have an impact on the style-property of the object it belongs to.
I tried different ways, but without success... I also tried to define the style first and then change the template, but it does not work either.
Thank you all for your help!
So you can't set Style Property in Style with Setter. For this you need to use BasedOn:
<Style TargetType="ListBoxItem" BasedOn="{StaticResource DefaultListBoxItemStyle}">
<Setter ... />
</Style>

MenuItem icon returns collection

When I have a following code, it all works fine:
<Image x:Key="Icons" x:Shared="false"
Source="{Binding Path=Icon}" Height="16px" Width="16px"/>
<Style x:Key="MenuItemStyle" TargetType="MenuItem" >
<Setter Property="MenuItem.ItemsSource" Value="{Binding Children}"/>
<Setter Property="MenuItem.Header" Value="{Binding Text}"/>
<Setter Property="MenuItem.IsEnabled" Value="{Binding IsEnabled}"/>
<Setter Property="MenuItem.Icon" Value="{StaticResource Icons}"/>
</Style>
But I have to load xaml from external source and WPF has a bug that does not allow x:Shared= in that case. So I made Resource dictionary with x:Name=Icons that is compiled internally (Action is database table that has string property Icon and there is path to the Icon):
<Image x:Key="Icons" x:Shared="False"
Source="{Binding Path=Action.Icon}" Height="16px" Width="16px"/>
and the code now looks
<ResourceDictionary x:Key="IkoniceDict" Source="/MVVM_App;component/View/iconimage.xaml"/>
<Style x:Key="MenuItemStyle" TargetType="MenuItem">
<Setter Property="MenuItem.Icon" Value="{Binding Source={StaticResource Icons}}"/>
Problem is that now I get (collection) instead of image:
Need help, please!
You must not specify a key when loading a resource dictionary into the control.
<ResourceDictionary Source="/MVVM_App;component/View/iconimage.xaml"/>
Edit
I guess I'm not clear enough. The above only works if you have nothing but this in that single <SomeControl.Resources> tag.
<SomeControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionary>
<ResourceDictionary Source="/MVVM_App;component/View/iconimage.xaml"/>
</ResourceDictionary.MergedDictionary>
</ResourceDictionary>
<Style x:Key="MyStyleKey" .............>
</Style>
</SomeControl.Resources>
The Resources is a ResourceDictionary type. All entries must have an x:Key. If you assign an x:Key to an ResourceDictionary inside Resources tag, you are putting a dictionary inside dictionary. That is why you need to use ResourceDictionary.MergedDictionary to tell the XAML parser to merge the contents of iconimage.xaml in.
I think that you should set the Path property for your Binding (set it to "Source"):
<Style x:Key="MenuItemStyle" TargetType="MenuItem">
<Setter Property="MenuItem.Icon" Value="{Binding Path=Source, Source={StaticResource Icons}}"/>
When the path is not specified, the default is to bind to the entire object (in your case the collection of icons).
Msdn Binding

WPF RibbonButton: LargeImageSource and Label not updated via DataTriggers

I'm puzzled by a peculiar phenomenon in RibbonButton's behavior.
Everything works fine when I set the LargeImageSource and the Label statically in XAML:
<ribbon:RibbonButton x:Name="ButtonArchive"
LargeImageSource="..\Assets\archive_insert.png"
Label="{Binding Path=ItemArchiveButton,
Source={StaticResource Strings}}"/>
But when I try to modify these properties via DataTriggers - nothing seems to be happening.
The triggers do work; I can see the other properties - like Command or IsEnabled - set OK in the same trigger. It's just these too...
Here's the XAML:
<ribbon:RibbonButton x:Name="ButtonArchive"
LargeImageSource="..\Assets\archive_insert.png"
Label="{Binding Path=ItemArchiveButton, Source={StaticResource Strings}}">
<ribbon:RibbonButton.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding ="{Binding ElementName=ItemsList, Path=SelectedItem.IsArchived}" Value="false">
<Setter Property="ribbon:RibbonButton.Command" Value="{Binding ArchiveItemCommand}" />
<Setter Property="ribbon:RibbonButton.LargeImageSource" Value="..\Assets\archive_insert.png" />
<Setter Property="ribbon:RibbonButton.Label" Value="{Binding Path=ItemArchiveButton, Source={StaticResource Strings}}" />
</DataTrigger>
<DataTrigger Binding ="{Binding ElementName=ItemsList, Path=SelectedItem.IsArchived}" Value="true">
<Setter Property="ribbon:RibbonButton.Command" Value="{Binding RestoreItemCommand}" />
<Setter Property="ribbon:RibbonButton.LargeImageSource" Value="..\Assets\archive_extract.png" />
<Setter Property="ribbon:RibbonButton.Label" Value="{Binding Path=ItemRestoreButton, Source={StaticResource Strings}}" />
</DataTrigger>
</Style.Triggers>
</Style>
</ribbon:RibbonButton.Style>
</ribbon:RibbonButton>
Setting the Command works fine in the both conditions, but not the other 2 properties...
Any advice will be welcome.
I asked the same question at the MSDN forum, and the answer I've got really solved this.
The problem is your setting properties for LargeImageSource and Label in the button itself. When you do this it takes precidence over your style triggers. I suggest using setters in the style to set your defaults, and remove the property settings it the button.

Can I get this binding into a style?

I would like to take the xaml I currently have for a ComboBox (below), and condense it into something like the Style also shown below. I think this should work, but I have a 'Type'ing issue and not sure how to resolve it
"Cannot resolve the Style Property 'Margin'. Verify that the owning type is the Style's TargetType, or use Class.Property syntax to specify the Property.)
As I look at the existing ComboBoxStyle (also below) that I'm looking to base this new style off of, I see that I hadn't used x:Type, but it does seem to work.
Is there any reason this new style shouldn't work? What must I change?
Cheers,
Berryl
combo box, as is, working):
<ComboBox
x:Name="cboDepartmentFilter" Style="{StaticResource ComboBoxStyle}"
Margin="{StaticResource FliterPanelItem_Margin}" Width="{StaticResource FilterPanelItem_Width}"
ItemsSource="{Binding Path=DepartmentFilterControl.Choices}"
ToolTip="{Binding DepartmentFilterControlData.ToolTipTitle}"
/>
what I want:
<ComboBox Style="{StaticResource FilterPanelComboBoxStyle}" DataContext="{Binding DepartmentFilterControl}" />
<!- in some resource file ->
<Style x:Key="FilterPanelComboBoxStyle" BasedOn="{StaticResource ComboBoxStyle}">
<Setter Property="Margin" Value="{StaticResource FliterPanelItem_Margin}" />
<Setter Property="Width" Value="{StaticResource FilterPanelItem_Width}" />
<Setter Property="ItemsSource" Value="{Binding Choices}" />
<Setter Property="ToolTip" Value="{Binding ToolTipTitle}" />
</Style>
<!--
This style defines a common margin for items in a filter panel.
-->
150
existing ComboBoxStyle:
<!-- ComboBox Style -->
<Style x:Key="ComboBoxStyle" TargetType="ComboBox">
<Setter Property="Background" Value="{StaticResource headerBrush}" />
...
<Setter Property="Template">
<Setter.Value>
...
</Setter.Value>
</Setter>
<Setter Property="ItemContainerStyle" Value="{StaticResource ComboBoxItemStyle}" />
<Setter Property="IsSynchronizedWithCurrentItem" Value="True" />
</Style>
You still need to specify the TargetType in the derived style. (Or you prefix the properties with "ComboBox.")

How do I change the CellErrorStyle for an Xceed Datagrid?

So in the Xceed documentation there is a code example that does not work for me. It may be because my grid is bound to a DataGridCollectionView. The objects in the collection used by the datagridcollection are what implement IDataErrorInfo.
The errors are showing up just fine. The problem is that they are using the default orange background for errors...I need a red border. Below is the XAML instantiation of my grid. I set the DataCell background property to red just so I could be sure I had access to the grid's properties... I do. I just can't find the way to identify the cell's w/ errors so I can style them. Thanks!
<XceedDG:DataGridControl Grid.Row="1" Grid.ColumnSpan="5" ItemsSource="{Binding Path = ABGDataGridCollectionView, UpdateSourceTrigger=PropertyChanged}"
Background="{x:Static Views:DataGridControlBackgroundBrushes.ElementalBlue}" IsDeleteCommandEnabled="True"
FontSize="16" AutoCreateColumns="False" x:Name="EncounterDataGrid" AllowDrop="True">
<XceedDG:DataGridControl.View>
<Views:TableView ColumnStretchMode="All" ShowRowSelectorPane="True"
ColumnStretchMinWidth="100">
<Views:TableView.FixedHeaders>
<DataTemplate>
<XceedDG:InsertionRow Height="40"/>
</DataTemplate>
</Views:TableView.FixedHeaders>
</Views:TableView>
</XceedDG:DataGridControl.View>
<!--Group Header formatting-->
<XceedDG:DataGridControl.Resources>
<Style TargetType="{x:Type XceedDG:GroupByControl}">
<Setter Property="Visibility" Value="Collapsed"/>
</Style>
<Style TargetType="{x:Type XceedDG:DataCell}">
<Setter Property="Background" Value="Red"/>
</Style>
</XceedDG:DataGridControl.Resources>
...
The knowledge base entry:
http://xceed.com/KB/questions.php?questionid=256
Does seem to be potentially missing a critical piece.
Did you try the CellErrorStyle Property on DataGridView?
<Grid xmlns:xcdg="http://schemas.xceed.com/wpf/xaml/datagrid">
<Grid.Resources>
<Style x:Key="errorStyle" TargetType="{x:Type xcdg:DataCell}">
<Setter Property="Foreground" Value="Red"/>
</Style>
</Grid.Resources>
<xcdg:DataGridControl CellErrorStyle="{StaticResource errorStyle}" >
<!--STUFF OMITTED-->
</xcdg:DataGridControl>
</xcdg:DataGridControl>

Resources