In our project we have a LookUp Base ViewModel which has a Required-Attribute on the SelectedItem property. I have another View that uses one of the child LookUps, which should ignore the Required-attribute. I've already overridden the IsValid method in the ViewModel, so saving without caring about the Required works correctly, but unfortunately it's still showing the validation error on the view when I empty the LookUp:
I had a couple of possibilities:
Split the LookUpBaseViewModel into two childs that are also "BaseViewModels", one with the RequiredAttribute and one without. This works, but it seems like a bit too much work and a lot of extra classes for just a single view that doesn't need to show the validation errors on the View.
Replace the RequiredAttribute with a RequiredIf-Attribute and add a boolean IsRequired parameter to the Constructor. This doesn't work since we use AutoFac in our project, so we can't use a boolean parameter for the ILookUpBaseViewModel-interface implementation.
Add a style to the LookUp-ContentControl in the View to hide the ValidationError border & text. This seemed like the easiest solution on paper, and it also makes sense to just hide the unwanted ValidationError border & text.
So, my question, how do I make the style to hide the default WPF validation error (so the red border and the text behind it)? I'm a novice when it comes to styles, but this is what I've tried (and which doesn't do anything it seems):
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="HideValidationErrorContentControlStyle" TargetType="{x:Type ContentControl}" BasedOn="{StaticResource {x:Type ContentControl}}">
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<!-- Empty -->
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<!-- Empty -->
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
With the style on my LookUp-ContentControl like this:
<ContentControl x:Name="MyLookup" Style="{StaticResource HideValidationErrorContentControlStyle}"/>
This is the result I want (even when a ValidationError would normally be shown):
Maybe it isn't your LookUp-ContentControl the one showing the error, but another control inside it. A TextBox, maybe?
Also, instead of leaving the ErrorTemplate empty, try to add an AdornedElementPlaceholder.
<Style x:Key="HideValidationErrorContentControlStyle" TargetType="{x:Type ContentControl}" BasedOn="{StaticResource {x:Type ContentControl}}">
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<AdornedElementPlaceholder />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
It's likely this isn't needed, but better be safe than sorry.
Related
I'm currently looking at the UWP CommunityToolkit DataGrid. I've been through the docs, but I'm not finding them clear on how to apply a ColumnHeaderStyle. I'm not sure what I should be targeting in the column header to set my style. I'm wishing to change the background and foreground colors. I would also like these properties to apply across the whole header, not just individual columns.
<controls:DataGrid.ColumnHeaderStyle>
<Style TargetType="">
<Setter Property="" Value=""/>
</Style>
</controls:DataGrid.ColumnHeaderStyle>
This one had me puzzled for a while, but I eventually discovered you need to add another XML namespace declaration in order to target the column header.
<Application
x:Class="MyApp"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
xmlns:controlsprimitives="using:Microsoft.Toolkit.Uwp.UI.Controls.Primitives">
So in this case I just appended:
xmlns:controlsprimitives="using:Microsoft.Toolkit.Uwp.UI.Controls.Primitives"
Then you can create a style with this target:
<Style x:Key="ColumnHeaderStyle" TargetType="controlsprimitives:DataGridColumnHeader">
<!-- style properties -->
</Style>
(As of writing this, however, there seems to be weird styling behavior in doing this for some reason.)
You can override DataGridColumnHeaderBackgroundBrush and DataGridColumnHeaderForegroundBrush in your App.xaml as below:
<SolidColorBrush x:Key="DataGridColumnHeaderBackgroundBrush" Color="#FFCB2128" />
<SolidColorBrush x:Key="DataGridColumnHeaderForegroundBrush" Color="#FFB03060" />
The answer from #user1559112 got me on the right track, but it took some time to realize that in order to deal with the "weird styling behavior", it wasn't enough to just add a setter for the Background. I had to override the template like this:
<controls:DataGrid.ColumnHeaderStyle>
<Style TargetType="controlsprimitives:DataGridColumnHeader">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="{Binding}" />
</DataTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="prms:DataGridColumnHeader">
<ContentPresenter Background="{ThemeResource HeaderBackgroundBrush}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</controls:DataGrid.ColumnHeaderStyle>
I use a custom control from an external library, it has a property with ControlTemplate.
<Style x:Key="{x:Type controls:HeaderDiscountButton}" TargetType="{x:Type controls:HeaderDiscountButton}" BasedOn="{StaticResource {x:Type core:ValueButton}}">
<Setter Property="core:ButtonWithPopup.PopupTemplate">
<Setter.Value>
<ControlTemplate>
some complicated xaml code
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I would like to override it, but use old one in my new ControlTemplate, for example
<Style x:Key="{x:Type controls:HeaderDiscountButton}" TargetType="{x:Type controls:HeaderDiscountButton}" BasedOn="{StaticResource {x:Type core:ValueButton}}">
<Setter Property="core:ButtonWithPopup.PopupTemplate">
<Setter.Value>
<ControlTemplate>
<StackPanel>
<Border>some complicated xaml code</Border>
<Border>some additional xaml code</Border>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I would like to avoid copying whole old code
This is not possible I am afraid. You can indeed base a Style on another Style and override specfic setters but you cannot "override" or inherit only a part of a ControlTemplate. Unfortunately you must (re)define the entire template as a whole.
So in this case you actually need to copy the (whole) original template and then edit it as per your requirements.
I made a custom resource dictionary style for a TreeViewItem, but I am having difficulties with it.
<Style x:Key="StageTreeViewItem" TargetType="{x:Type TreeViewItem}" BasedOn="{StaticResource {x:Type TreeViewItem}}">
<Setter Property="Foreground" Value="Gold"/>
<Setter Property="FontFamily" Value="ArialN"/>
<Setter Property="FontSize" Value="20"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TreeViewItem">
<Grid>
<Image Name="PrimaryButtonImage" Source="pack://application:,,,/Images/TreeViewItem/TreeViewItem_Normal.png"/>
<ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The content/header of the TreeViewItem does not exist. I put "Stage One" as Header of the TreeViewItem, but it doesn't show up. Also, if I add multiple tree view items on another, it does not expand at all.
Another thing:
How can I remove the highlights when I select the tree view item? I want it to be transparent even when I hover over it and even when I click it. I don't want anything to happen, but I just don't know how, I tried everything.
Your provided code is not making it clear how you're setting header of TreeViewItem.
For other part of the question, you can use Triggers for events happening in WPF forms. Also have a look at this link, as you'll have to define a template for changing background color on mouse hover.
IsMouseOver Trigger not working in WPF
I've got a custom control in WPF, which has a variety of dependency properties that allow visual customization. For the sake of brevity I won't post the entire control, but it basically is setup like this:
<UserControl.Resources>
<Style TargetType="{x:Type MyControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type MyControl}">
<Border BorderBrush="{TemplateBinding BorderColor}">
// more stuff here
<ContentPresenter/>
</Border>
</ControlTemplate>
</Setter>
</Setter>
</Style>
</UserControl.Resources>
The BorderColor property works fine if I set it directly, like this:
<ctl:MyControl BorderColor="Brushes.Red">....</ctl:MyControl>
But I want to set it application-wide. The problem I have is if I simply set the style with no key, it does not apply. Like this:
<Window.Resources>
<Style TargetType="{x:Type ctl:MyControl}">
<Setter Property="BorderColor" Value="Brushes.Red"/>
</Style>
</Window.Resources>
This does not do anything to the control. So I thought I'd just set a key and apply that style, like this:
<Style TargetType="{x:type ctl:MyControl}" x:Key="myStyle">....</Style>
<ctl:MyControl Style="{StaticResource myStyle}">.....</ctl:MyControl>
But this causes the control to vanish, I'm assuming because it's removing the Template. What am I doing wrong? With other framework controls you can just set the properties you want without losing the control template.
You need to inherit from the default style you have created.
inherit style from default style
I have a view that Filters a DataGrid and I want to use the the exact same filtering with the same collection (apart from the columns will be different) in a different view.
Of course I dont want to duplicate the XAML in this new view, so is this when a user control would be the correct thing to do?
My only problem is that a new DataGrid will be put underneath in the new view so would this be possible? And as I said above, the columns also may be different in the filtering, so again, possible within a user control?
Thanks
A UserControl should be used when wanting to create a new kind of control for your UI, or derive an existing control and enhance its capabilities.
What you need sounds like a Style, where you want to set certian properties of your control to certian values:
<Style TargetType="Button">
<Setter Property="Background" Value="Red"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<Rectangle Fill="{TemplateBinding Background"/>
<ContentPresenter/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>