WPF中override ResourceDictionary中的设置的方法

时间:2023-03-09 17:11:29
WPF中override ResourceDictionary中的设置的方法

当资源文件里改变了控件的样式时,在使用的地方如果想改变资源文件里修改的内容,会造成无法达到预期目的的结果。

以DataGrid为例,我在资源文件里,改变了默认的DataGrid的样式,其中我设置了IsReadOnly为True。在使用时,这将导致DataGrid的列不能编辑;可实际情况要求编辑功能,我们就会想到针对列设置IsReadOnly为false。

如代码里的注释掉的内容所示,在简单地引用资源文件,而不做处理时,是无法达到预期的。

正确的做法是:

引入通过引入新的Style,在Style的Setter里设置,来override资源文件里的设置;这样再针对每个列单独设置IsReadOnly就会起作用。

其中的原理还没有太明白,仅仅记录下处理方法。

界面

 <Window x:Class="learnwpf.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" WindowStartupLocation="CenterScreen">
<Grid>
<DataGrid x:Name="dg" AutoGenerateColumns="False"
CanUserAddRows="False" CanUserDeleteRows="False" CanUserReorderColumns="False"
CanUserResizeColumns="False" CanUserResizeRows="False" CanUserSortColumns="False">
<!--以下这样的字典引用方式,将导致即使在DataGridTextColumn里设置IsReadOnly为false仍旧不能编辑-->
<!--<DataGrid.Resources>
<ResourceDictionary Source="newlook/DataGrid.xaml" />
</DataGrid.Resources>-->
<!--解决办法如下,注意x:key的使用-->
<DataGrid.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="newlook/DataGrid.xaml" />
<ResourceDictionary>
<Style TargetType="DataGrid">
<Setter Property="IsReadOnly" Value="False" />
</Style>
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn x:Name="text" Header="文本" Binding="{Binding Name,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" IsReadOnly="True" />
<DataGridTextColumn x:Name="combo" Header="选择" Binding="{Binding Class,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" />
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>

资源文件

 <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <SolidColorBrush x:Key="GridHeaderForeground" Color="#333"/>
<SolidColorBrush x:Key="GridHeaderLineBrush" Color="#FFCCCEDB"/>
<SolidColorBrush x:Key="GridHeaderBackgroudBrush" Color="#FFE3E3E3"/>
<SolidColorBrush x:Key="GridLineBrush" Color="#FFEFEFF2"/>
<SolidColorBrush x:Key="GridDrakRow" Color="#FFF9F9F9"/>
<SolidColorBrush x:Key="GridBorderBrush" Color="#FFCCCEDB"/> <Style x:Key="ColumnHeaderGripperStyle" TargetType="{x:Type Thumb}">
<Setter Property="Width" Value="3" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="Cursor" Value="SizeWE" />
<Setter Property="Opacity" Value="0" />
</Style> <Style TargetType="DataGrid">
<Setter Property="Margin" Value="0"/>
<Setter Property="CanUserResizeColumns" Value="True"/>
<Setter Property="CanUserSortColumns" Value="False"/>
<Setter Property="AutoGenerateColumns" Value="False"/>
<Setter Property="CanUserResizeRows" Value="False"/>
<Setter Property="SelectionMode" Value="Single"/>
<Setter Property="RowHeaderWidth" Value="0"/>
<Setter Property="CanUserAddRows" Value="False"/>
<Setter Property="CanUserDeleteRows" Value="False"/>
<Setter Property="IsReadOnly" Value="True"/>
<Setter Property="Background" Value="AliceBlue" />
<Setter Property="AlternationCount" Value="2" />
<Setter Property="ClipToBounds" Value="True" />
<Setter Property="BorderBrush" Value="{DynamicResource GridBorderBrush}" />
<Setter Property="HorizontalGridLinesBrush" Value="{DynamicResource GridLineBrush}"/>
<Setter Property="VerticalGridLinesBrush" Value="{DynamicResource GridLineBrush}"/>
</Style> <Style TargetType="DataGridColumnHeader">
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="Foreground" Value="{DynamicResource GridHeaderForeground}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="DataGridColumnHeader">
<Border x:Name="BackgroundBorder" BorderThickness="1,0,1,1"
Margin="-1,0,0,0"
Background="{DynamicResource GridHeaderBackgroudBrush}"
BorderBrush="{DynamicResource GridHeaderLineBrush}" Width="Auto">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ContentPresenter Margin="0,0,0,0" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<Thumb x:Name="PART_LeftHeaderGripper" HorizontalAlignment="Left" Style="{StaticResource ColumnHeaderGripperStyle}" />
<Thumb x:Name="PART_RightHeaderGripper" HorizontalAlignment="Right" Style="{StaticResource ColumnHeaderGripperStyle}" />
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Height" Value="25"/>
</Style> <Style TargetType="{x:Type DataGridRow}">
<Setter Property="Background" Value="Beige" />
<Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="Height" Value="24" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridRow}">
<Border x:Name="DGR_Border" SnapsToDevicePixels="True">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Unfocused_Selected">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="DGR_Border" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="00:00:00" Value="{DynamicResource CtrlSelectedUnFocusBG}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Normal_AlternatingRow">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="DGR_Border" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="00:00:00" Value="{StaticResource GridDrakRow}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="MouseOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="DGR_Border" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="00:00:00" Value="{DynamicResource CtrlMouseOverBG}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Normal_Selected">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="DGR_Border" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="00:00:00" Value="{DynamicResource CtrlSelectedBG}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<SelectiveScrollingGrid>
<SelectiveScrollingGrid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</SelectiveScrollingGrid.ColumnDefinitions>
<SelectiveScrollingGrid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</SelectiveScrollingGrid.RowDefinitions>
<DataGridCellsPresenter Grid.Column="1"
ItemsPanel="{TemplateBinding ItemsPanel}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
<DataGridDetailsPresenter Grid.Column="1"
Grid.Row="1"
Visibility="{TemplateBinding DetailsVisibility}"
SelectiveScrollingGrid.SelectiveScrollingOrientation=
"{Binding AreRowDetailsFrozen,
ConverterParameter={x:Static SelectiveScrollingOrientation.Vertical},
Converter={x:Static DataGrid.RowDetailsScrollingConverter},
RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"/>
<DataGridRowHeader Grid.RowSpan="2"
SelectiveScrollingGrid.SelectiveScrollingOrientation="Vertical"
Visibility="{Binding HeadersVisibility,
ConverterParameter={x:Static DataGridHeadersVisibility.Row},
Converter={x:Static DataGrid.HeadersVisibilityConverter},
RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
</SelectiveScrollingGrid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="Black" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style> </ResourceDictionary>

逻辑

 using System.Collections.Generic;
using System.Windows; namespace learnwpf
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
init();
} private class TestData
{
public string Name { get; set; }
public string Class { get; set; }
} private void init()
{
List<TestData> data = new List<TestData>()
{
new TestData(){Name="first",Class=""},
new TestData(){Name="secon",Class=""},
};
dg.ItemsSource = data;
}
}
}