为什么我在 Generic.xaml 中的样式不起作用?

发布于 2025-01-07 21:27:26 字数 9828 浏览 1 评论 0原文

我正在清理 App.xaml 并将一些样式移至 Generic.xaml 中。但是,这些样式没有任何效果。为什么?为了使 App.xaml 整洁,这样做是否正确?

编辑(包括一些源代码):

目标是重新设置 WPF DataGrid 的样式,使滚动条从上到下、从左到右运行(默认样式不包括行和列标题)。

当我将其放入 App.xaml 中时,该样式正在工作。因为它是一大块代码,所以我想将其从 App.xaml 移到 /Themes/DataGridEx.xaml 中。顺便说一句,DataGridEx 是我从 WPF DataGrid 派生的扩展类。

这是我的 DataGrid.xaml:

<ControlTemplate x:Key="SelectAllButtonTemplate" TargetType="{x:Type Button}">
    <Grid>
        <Rectangle x:Name="Border"
             Fill="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" 
             SnapsToDevicePixels="True" />
        <Polygon x:Name="Arrow"
           HorizontalAlignment="Right"
           VerticalAlignment="Bottom"
           Margin="8,8,3,3"
           Opacity="0.15"
           Fill="Black"
           Stretch="Uniform"
           Points="0,10 10,10 10,0" />
    </Grid>
    <ControlTemplate.Triggers>
        <Trigger Property="IsMouseOver" Value="True">
            <Setter TargetName="Border" Property="Stroke" Value="{DynamicResource {x:Static SystemColors.ControlDarkBrushKey}}" />
        </Trigger>
        <Trigger Property="IsPressed" Value="True">
            <Setter TargetName="Border" Property="Fill" Value="{DynamicResource {x:Static SystemColors.ControlDarkBrushKey}}" />
        </Trigger>
        <Trigger Property="IsEnabled" Value="False">
            <Setter TargetName="Arrow" Property="Visibility" Value="Collapsed" />
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

<Style TargetType="{x:Type local:DataGridEx}" x:Key="{x:Type local:DataGridEx}">
    <Setter Property="Background"
            Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
    <Setter Property="Foreground"
            Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
    <Setter Property="BorderBrush" Value="#FF688CAF" />
    <Setter Property="BorderThickness" Value="1" />
    <Setter Property="RowDetailsVisibilityMode" Value="VisibleWhenSelected" />
    <Setter Property="ScrollViewer.CanContentScroll"
            Value="true"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:DataGridEx}">
                <Border Background="{TemplateBinding Background}"
              BorderBrush="{TemplateBinding BorderBrush}"
              BorderThickness="{TemplateBinding BorderThickness}"
              SnapsToDevicePixels="True"
              Padding="{TemplateBinding Padding}">
                    <ScrollViewer   Focusable="false"
                        Name="DG_ScrollViewer">
                        <ScrollViewer.Template>
                            <ControlTemplate TargetType="{x:Type ScrollViewer}">
                                <Grid>
                                    <Grid.RowDefinitions>
                                        <RowDefinition Height="Auto"/>
                                        <RowDefinition Height="*"/>
                                        <RowDefinition Height="Auto"/>
                                    </Grid.RowDefinitions>

                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="Auto"/>
                                        <ColumnDefinition Width="*"/>
                                        <ColumnDefinition Width="Auto"/>
                                    </Grid.ColumnDefinitions>

                                    <!--Left Column Header Corner -->
                                    <Button Command="{x:Static local:DataGridEx.SelectAllCommand}"
                        Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:DataGridEx}}, Path=CellsPanelHorizontalOffset}"
                        Template="{StaticResource SelectAllButtonTemplate}"
                        Focusable="false"
                        Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:DataGridEx}}, Path=HeadersVisibility, Converter={x:Static local:DataGridEx.HeadersVisibilityConverter}, ConverterParameter={x:Static DataGridHeadersVisibility.All}}" />
                                    <!--Column Headers-->
                                    <DataGridColumnHeadersPresenter Grid.Column="1" 
                                                   x:Name="PART_ColumnHeadersPresenter"
                                                   Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:DataGridEx}}, Path=HeadersVisibility, Converter={x:Static DataGrid.HeadersVisibilityConverter}, ConverterParameter={x:Static DataGridHeadersVisibility.Column}}"/>

                                    <!--DataGrid content-->
                                    <ScrollContentPresenter x:Name="PART_ScrollContentPresenter" Grid.Row="1" Grid.ColumnSpan="2" CanContentScroll="{TemplateBinding CanContentScroll}" />

                                    <!-- Changed Grid.Row="1" to Grid.Row="0" Grid.RowSpan="2" to make the scrollbar start from top -->
                                    <ScrollBar Grid.Row="0" Grid.RowSpan="2" Grid.Column="2" Name="PART_VerticalScrollBar"
                                         Orientation="Vertical"
                                         Maximum="{TemplateBinding ScrollableHeight}"
                                         ViewportSize="{TemplateBinding ViewportHeight}"
                                         Value="{Binding Path=VerticalOffset, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}"
                                         Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"/>

                                    <!--Grid Grid.Row="2" Grid.Column="1">
                  <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type dg:DataGrid}}, Path=NonFrozenColumnsViewportHorizontalOffset}"/>
                    <ColumnDefinition Width="*"/>
                  </Grid.ColumnDefinitions>
                  <ScrollBar Grid.Column="1"
                             Name="PART_HorizontalScrollBar"
                             Orientation="Horizontal"
                             Maximum="{TemplateBinding ScrollableWidth}"
                             ViewportSize="{TemplateBinding ViewportWidth}"
                             Value="{Binding Path=HorizontalOffset, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}"
                             Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"/>

                </Grid-->
                                    <!-- Make the scrollbar to start from left edge -->
                                    <ScrollBar Grid.Column="0" Grid.Row="2" Grid.ColumnSpan="2"
                                            Name="PART_HorizontalScrollBar"
                                            Orientation="Horizontal"
                                            Maximum="{TemplateBinding ScrollableWidth}"
                                            ViewportSize="{TemplateBinding ViewportWidth}"
                                            Value="{Binding Path=HorizontalOffset, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}"
                                            Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"/>
                                </Grid>
                            </ControlTemplate>
                        </ScrollViewer.Template>
                        <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                    </ScrollViewer>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <Trigger Property="IsGrouping" Value="true">
            <Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
        </Trigger>
    </Style.Triggers>
</Style>

这是我的主题/Generic.xaml:

<ResourceDictionary.MergedDictionaries>
    <ResourceDictionary Source="/Themes/DataGridEx.xaml"/>
    <ResourceDictionary Source="/Themes/GridComboBox.xaml"/>
</ResourceDictionary.MergedDictionaries>

这是我的 App.xaml:

    <Application x:Class="MyApp.App"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:local="clr-namespace:MyApp.Common"
                 DispatcherUnhandledException="Application_DispatcherUnhandledException">
                 <!--StartupUri="MainWindow.xaml"-->
        <Application.Resources>
            <ResourceDictionary x:Key="rd">
                <ResourceDictionary.MergedDictionaries>
                    <ResourceDictionary Source="Themes/Generic.xaml"/>
                </ResourceDictionary.MergedDictionaries>
            </ResourceDictionary>
....
        </Application.Resources>
    </Application>

使用此代码,我收到运行时 XamlParseException:“无法从文本“local:DataGridEx”创建“类型””。但是,如果我在 App.xaml 中注释掉 MergedDictionaries,它不会抱怨,但样式也不会生效。

另一个有趣的事情是,在这个 generic.xaml 中我有两个字典。如果我从 App.xaml 中删除 ResourceDictionary,GridComboBox.xaml 可以正常工作,但 DataGridEx.xaml 则不能。

I'm cleaning up App.xaml and moved some styles into Generic.xaml. But then, these styles don't have any effect. Why? Is this correct thing to do to make App.xaml tidy?

EDIT (to include some source code):

The goal is to restyle WPF DataGrid to make the scrollbars run from top to bottom and from left to right (default style excludes row and column header).

The style is working when I put it in App.xaml. Because it's a big chunk of code, I'd like to move it out of App.xaml into /Themes/DataGridEx.xaml. By the way, DataGridEx is my extended class derived from WPF DataGrid.

This is my DataGrid.xaml:

<ControlTemplate x:Key="SelectAllButtonTemplate" TargetType="{x:Type Button}">
    <Grid>
        <Rectangle x:Name="Border"
             Fill="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" 
             SnapsToDevicePixels="True" />
        <Polygon x:Name="Arrow"
           HorizontalAlignment="Right"
           VerticalAlignment="Bottom"
           Margin="8,8,3,3"
           Opacity="0.15"
           Fill="Black"
           Stretch="Uniform"
           Points="0,10 10,10 10,0" />
    </Grid>
    <ControlTemplate.Triggers>
        <Trigger Property="IsMouseOver" Value="True">
            <Setter TargetName="Border" Property="Stroke" Value="{DynamicResource {x:Static SystemColors.ControlDarkBrushKey}}" />
        </Trigger>
        <Trigger Property="IsPressed" Value="True">
            <Setter TargetName="Border" Property="Fill" Value="{DynamicResource {x:Static SystemColors.ControlDarkBrushKey}}" />
        </Trigger>
        <Trigger Property="IsEnabled" Value="False">
            <Setter TargetName="Arrow" Property="Visibility" Value="Collapsed" />
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

<Style TargetType="{x:Type local:DataGridEx}" x:Key="{x:Type local:DataGridEx}">
    <Setter Property="Background"
            Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
    <Setter Property="Foreground"
            Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
    <Setter Property="BorderBrush" Value="#FF688CAF" />
    <Setter Property="BorderThickness" Value="1" />
    <Setter Property="RowDetailsVisibilityMode" Value="VisibleWhenSelected" />
    <Setter Property="ScrollViewer.CanContentScroll"
            Value="true"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:DataGridEx}">
                <Border Background="{TemplateBinding Background}"
              BorderBrush="{TemplateBinding BorderBrush}"
              BorderThickness="{TemplateBinding BorderThickness}"
              SnapsToDevicePixels="True"
              Padding="{TemplateBinding Padding}">
                    <ScrollViewer   Focusable="false"
                        Name="DG_ScrollViewer">
                        <ScrollViewer.Template>
                            <ControlTemplate TargetType="{x:Type ScrollViewer}">
                                <Grid>
                                    <Grid.RowDefinitions>
                                        <RowDefinition Height="Auto"/>
                                        <RowDefinition Height="*"/>
                                        <RowDefinition Height="Auto"/>
                                    </Grid.RowDefinitions>

                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="Auto"/>
                                        <ColumnDefinition Width="*"/>
                                        <ColumnDefinition Width="Auto"/>
                                    </Grid.ColumnDefinitions>

                                    <!--Left Column Header Corner -->
                                    <Button Command="{x:Static local:DataGridEx.SelectAllCommand}"
                        Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:DataGridEx}}, Path=CellsPanelHorizontalOffset}"
                        Template="{StaticResource SelectAllButtonTemplate}"
                        Focusable="false"
                        Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:DataGridEx}}, Path=HeadersVisibility, Converter={x:Static local:DataGridEx.HeadersVisibilityConverter}, ConverterParameter={x:Static DataGridHeadersVisibility.All}}" />
                                    <!--Column Headers-->
                                    <DataGridColumnHeadersPresenter Grid.Column="1" 
                                                   x:Name="PART_ColumnHeadersPresenter"
                                                   Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:DataGridEx}}, Path=HeadersVisibility, Converter={x:Static DataGrid.HeadersVisibilityConverter}, ConverterParameter={x:Static DataGridHeadersVisibility.Column}}"/>

                                    <!--DataGrid content-->
                                    <ScrollContentPresenter x:Name="PART_ScrollContentPresenter" Grid.Row="1" Grid.ColumnSpan="2" CanContentScroll="{TemplateBinding CanContentScroll}" />

                                    <!-- Changed Grid.Row="1" to Grid.Row="0" Grid.RowSpan="2" to make the scrollbar start from top -->
                                    <ScrollBar Grid.Row="0" Grid.RowSpan="2" Grid.Column="2" Name="PART_VerticalScrollBar"
                                         Orientation="Vertical"
                                         Maximum="{TemplateBinding ScrollableHeight}"
                                         ViewportSize="{TemplateBinding ViewportHeight}"
                                         Value="{Binding Path=VerticalOffset, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}"
                                         Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"/>

                                    <!--Grid Grid.Row="2" Grid.Column="1">
                  <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type dg:DataGrid}}, Path=NonFrozenColumnsViewportHorizontalOffset}"/>
                    <ColumnDefinition Width="*"/>
                  </Grid.ColumnDefinitions>
                  <ScrollBar Grid.Column="1"
                             Name="PART_HorizontalScrollBar"
                             Orientation="Horizontal"
                             Maximum="{TemplateBinding ScrollableWidth}"
                             ViewportSize="{TemplateBinding ViewportWidth}"
                             Value="{Binding Path=HorizontalOffset, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}"
                             Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"/>

                </Grid-->
                                    <!-- Make the scrollbar to start from left edge -->
                                    <ScrollBar Grid.Column="0" Grid.Row="2" Grid.ColumnSpan="2"
                                            Name="PART_HorizontalScrollBar"
                                            Orientation="Horizontal"
                                            Maximum="{TemplateBinding ScrollableWidth}"
                                            ViewportSize="{TemplateBinding ViewportWidth}"
                                            Value="{Binding Path=HorizontalOffset, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}"
                                            Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"/>
                                </Grid>
                            </ControlTemplate>
                        </ScrollViewer.Template>
                        <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                    </ScrollViewer>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <Trigger Property="IsGrouping" Value="true">
            <Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
        </Trigger>
    </Style.Triggers>
</Style>

This is my Themes/Generic.xaml:

<ResourceDictionary.MergedDictionaries>
    <ResourceDictionary Source="/Themes/DataGridEx.xaml"/>
    <ResourceDictionary Source="/Themes/GridComboBox.xaml"/>
</ResourceDictionary.MergedDictionaries>

This is my App.xaml:

    <Application x:Class="MyApp.App"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:local="clr-namespace:MyApp.Common"
                 DispatcherUnhandledException="Application_DispatcherUnhandledException">
                 <!--StartupUri="MainWindow.xaml"-->
        <Application.Resources>
            <ResourceDictionary x:Key="rd">
                <ResourceDictionary.MergedDictionaries>
                    <ResourceDictionary Source="Themes/Generic.xaml"/>
                </ResourceDictionary.MergedDictionaries>
            </ResourceDictionary>
....
        </Application.Resources>
    </Application>

With this code, I got a run-time XamlParseException: "Failed to create a 'Type' from the text 'local:DataGridEx'". However, if I comment out the MergedDictionaries in App.xaml, it doesn't complain, but the style doesn't take effect either.

Another interesting thing is that, in this generic.xaml I have two dictionaries. If I remove the ResourceDictionary from App.xaml, GridComboBox.xaml is working fine, but DataGridEx.xaml is not.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

亽野灬性zι浪 2025-01-14 21:27:26

您需要将其合并到 App.xaml 中,如下所示:

<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="Generic.xaml"/>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Application.Resources>

如果您已经这样做了,则需要发布代码以提供更多信息。

编辑:
尝试按照此处的说明进行操作。特别是关于必须将字典设置为资源并使用源中的完整路径的部分。

You need to merge it into App.xaml like this:

<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="Generic.xaml"/>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Application.Resources>

If you are already doing that, you need to post your code to give more info.

EDIT:
Try following the instructions here. Particularly, the parts about having to set your dictionaries to Resource and using the full path in Source.

琉璃繁缕 2025-01-14 21:27:26

我遇到了这个问题,最简单的解决方法是删除 ResourceDictionary 中使用的样式的 x:Key 属性。

<ControlTemplate TargetType="{x:Type Button}">

I encountered this issue and the simplest fix for this is to remove the x:Key property of the style to be used in the ResourceDictionary.

<ControlTemplate TargetType="{x:Type Button}">
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文