无法解析样式、ResourceDictionary、UserControl
Cannot Resolve Style, ResourceDictionary, UserControl
这是迄今为止我在从事 WPF 工作的一年中遇到的最令人困惑的问题。对于使用 WPF 时间较长的人来说,问题的两个组成部分可能更能说明问题:
- 在
UserControl
中,我的 ResourceDictionary
元素抱怨它需要 Key
属性。
- 当我定义
Key
属性并尝试在设计时从 XAML 访问样式时,Intellisense(和编译器)不知道我导入的 [=15= 中定义的样式].
- 我正在尝试将样式应用于
MenuItem
上的 .ItemTemplate
这是我的 UserControl
XAML 资源声明,注意 x:Key
属性。
<UserControl.Resources>
<ResourceDictionary x:Key="HeaderViewStyles">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="../../Styles/Controls/HeaderViewStyles.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
这里是 ResourceDictionary
的部分实现,定义了我希望在 MenuItem
上使用的样式。
x:Class="Styles.Controls.HeaderViewStyles">
<Style x:Key="DarkMenuItem" TargetType="{x:Type MenuItem}">
<Setter Property="Foreground" Value="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type Menu}}}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type MenuItem}">
<!---
以上样式本身可能有问题;但是,我感兴趣的是 为什么我无法在设计时访问样式。
这是我应用样式的尝试(发布以获取完整信息):
<Menu>
<MenuItem ItemsSource="{Binding ContextMenuItemViewModels}">
<MenuItem.Icon>
<Image Source="../../Resources/menu.png"/>
</MenuItem.Icon>
<MenuItem.ItemTemplate>
<DataTemplate DataType="{x:Type controlViewModels:ContextMenuItemViewModel}">
<MenuItem Style="{DynamicResource DarkMenuItem}"
Header="{Binding MenuHeaderText}"
Command="{Binding MenuItemClickedCommand}"/>
</DataTemplate>
</MenuItem.ItemTemplate>
</MenuItem>
</Menu>
我相信这是多种因素的结合;但是,我显然缺乏一些知识。我错过了什么或没有做什么?我尝试了各种组合,但仍然无法选择风格。
编辑
想要了解更多信息的朋友,这里是我的控件XAML:
<UserControl x:Class="Views.Controls.HeaderView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controlViewModels="clr-namespace:ViewModels.Controls"
xmlns:controlViews="clr-namespace:Views.Controls"
xmlns:converters="clr-namespace:Converters"
VerticalContentAlignment="Stretch"
Background="#4C4C4C">
<UserControl.Resources>
<converters:SyncStateToVisibilityConverter x:Key="SyncStateToVisibilityConverter"/>
<ResourceDictionary x:Key="HeaderViewStyles">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="../../Styles/Controls/HeaderViewStyles.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="6"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="60"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="110"/>
</Grid.ColumnDefinitions>
<Button Background="#4C4C4C" Margin="20,0,0,0"
VerticalAlignment="Center"
Command="{Binding StatusButtonClickedCommand}">
<Image >
<Image.Style>
<Style TargetType="{x:Type Image}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="False">
<Setter Property="Source" Value="{Binding StatusIconLocation}"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Source" Value="{Binding StatusIconLocationHover}"/>
</Trigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</Button>
<StackPanel Grid.Column="1" Grid.ColumnSpan="2" Orientation="Vertical">
<TextBlock></TextBlock>
<TextBlock></TextBlock>
</StackPanel>
<Menu>
<MenuItem ItemsSource="{Binding ContextMenuItemViewModels}">
<MenuItem.Icon>
<Image Source="../../Resources/menu.png"/>
</MenuItem.Icon>
<MenuItem.ItemTemplate>
<DataTemplate DataType="{x:Type controlViewModels:ContextMenuItemViewModel}">
<MenuItem Style="{DynamicResource DarkMenuItem}"
Header="{Binding MenuHeaderText}"
Command="{Binding MenuItemClickedCommand}"/>
</DataTemplate>
</MenuItem.ItemTemplate>
</MenuItem>
</Menu>
<ProgressBar Grid.Row="1"
Grid.ColumnSpan="3"
Value="{Binding PercentageSynced}"
Visibility="{Binding CurrentSyncSystemStatus,
Converter={StaticResource SyncStateToVisibilityConverter},
ConverterParameter=Syncing,
FallbackValue=Collapsed}"/>
</Grid>
您需要将转换器移到资源字典中,并删除 x:Key,如下所示:
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="../../Styles/Controls/HeaderViewStyles.xaml"/>
</ResourceDictionary.MergedDictionaries>
<converters:SyncStateToVisibilityConverter x:Key="SyncStateToVisibilityConverter"/>
</ResourceDictionary>
</UserControl.Resources>
如果您将没有键的 ResourceDictionary 作为 UserControl.Resources
的根 - 这意味着:
userControl.Resources = new ResourceDictionary();
所以你必须把所有其他资源放在那个字典里面,而不是放在外面。
你原来的xaml(加上x:Key)大致意思是:
userControl.Resources.Add("SyncStateToVisibilityConverter", new YourConverter());
userControl.Resources.Add("HeaderViewStyles", new ResourceDictionary(...));
所以,不是您所期望的那样。
这是迄今为止我在从事 WPF 工作的一年中遇到的最令人困惑的问题。对于使用 WPF 时间较长的人来说,问题的两个组成部分可能更能说明问题:
- 在
UserControl
中,我的ResourceDictionary
元素抱怨它需要Key
属性。 - 当我定义
Key
属性并尝试在设计时从 XAML 访问样式时,Intellisense(和编译器)不知道我导入的 [=15= 中定义的样式]. - 我正在尝试将样式应用于
MenuItem
上的 .
ItemTemplate
这是我的 UserControl
XAML 资源声明,注意 x:Key
属性。
<UserControl.Resources>
<ResourceDictionary x:Key="HeaderViewStyles">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="../../Styles/Controls/HeaderViewStyles.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
这里是 ResourceDictionary
的部分实现,定义了我希望在 MenuItem
上使用的样式。
x:Class="Styles.Controls.HeaderViewStyles">
<Style x:Key="DarkMenuItem" TargetType="{x:Type MenuItem}">
<Setter Property="Foreground" Value="{Binding Path=Foreground, RelativeSource={RelativeSource AncestorType={x:Type Menu}}}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type MenuItem}">
<!---
以上样式本身可能有问题;但是,我感兴趣的是 为什么我无法在设计时访问样式。
这是我应用样式的尝试(发布以获取完整信息):
<Menu>
<MenuItem ItemsSource="{Binding ContextMenuItemViewModels}">
<MenuItem.Icon>
<Image Source="../../Resources/menu.png"/>
</MenuItem.Icon>
<MenuItem.ItemTemplate>
<DataTemplate DataType="{x:Type controlViewModels:ContextMenuItemViewModel}">
<MenuItem Style="{DynamicResource DarkMenuItem}"
Header="{Binding MenuHeaderText}"
Command="{Binding MenuItemClickedCommand}"/>
</DataTemplate>
</MenuItem.ItemTemplate>
</MenuItem>
</Menu>
我相信这是多种因素的结合;但是,我显然缺乏一些知识。我错过了什么或没有做什么?我尝试了各种组合,但仍然无法选择风格。
编辑
想要了解更多信息的朋友,这里是我的控件XAML:
<UserControl x:Class="Views.Controls.HeaderView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controlViewModels="clr-namespace:ViewModels.Controls"
xmlns:controlViews="clr-namespace:Views.Controls"
xmlns:converters="clr-namespace:Converters"
VerticalContentAlignment="Stretch"
Background="#4C4C4C">
<UserControl.Resources>
<converters:SyncStateToVisibilityConverter x:Key="SyncStateToVisibilityConverter"/>
<ResourceDictionary x:Key="HeaderViewStyles">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="../../Styles/Controls/HeaderViewStyles.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="6"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="60"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="110"/>
</Grid.ColumnDefinitions>
<Button Background="#4C4C4C" Margin="20,0,0,0"
VerticalAlignment="Center"
Command="{Binding StatusButtonClickedCommand}">
<Image >
<Image.Style>
<Style TargetType="{x:Type Image}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="False">
<Setter Property="Source" Value="{Binding StatusIconLocation}"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Source" Value="{Binding StatusIconLocationHover}"/>
</Trigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</Button>
<StackPanel Grid.Column="1" Grid.ColumnSpan="2" Orientation="Vertical">
<TextBlock></TextBlock>
<TextBlock></TextBlock>
</StackPanel>
<Menu>
<MenuItem ItemsSource="{Binding ContextMenuItemViewModels}">
<MenuItem.Icon>
<Image Source="../../Resources/menu.png"/>
</MenuItem.Icon>
<MenuItem.ItemTemplate>
<DataTemplate DataType="{x:Type controlViewModels:ContextMenuItemViewModel}">
<MenuItem Style="{DynamicResource DarkMenuItem}"
Header="{Binding MenuHeaderText}"
Command="{Binding MenuItemClickedCommand}"/>
</DataTemplate>
</MenuItem.ItemTemplate>
</MenuItem>
</Menu>
<ProgressBar Grid.Row="1"
Grid.ColumnSpan="3"
Value="{Binding PercentageSynced}"
Visibility="{Binding CurrentSyncSystemStatus,
Converter={StaticResource SyncStateToVisibilityConverter},
ConverterParameter=Syncing,
FallbackValue=Collapsed}"/>
</Grid>
您需要将转换器移到资源字典中,并删除 x:Key,如下所示:
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="../../Styles/Controls/HeaderViewStyles.xaml"/>
</ResourceDictionary.MergedDictionaries>
<converters:SyncStateToVisibilityConverter x:Key="SyncStateToVisibilityConverter"/>
</ResourceDictionary>
</UserControl.Resources>
如果您将没有键的 ResourceDictionary 作为 UserControl.Resources
的根 - 这意味着:
userControl.Resources = new ResourceDictionary();
所以你必须把所有其他资源放在那个字典里面,而不是放在外面。
你原来的xaml(加上x:Key)大致意思是:
userControl.Resources.Add("SyncStateToVisibilityConverter", new YourConverter());
userControl.Resources.Add("HeaderViewStyles", new ResourceDictionary(...));
所以,不是您所期望的那样。