wpf ResourceDictionary未应用于ContentControl

时间:2016-04-26 13:03:44

标签: c# wpf xaml

我有一个wpf应用程序,在这里我已经制作了一个带有标签和按钮的内容控制器。这将在加载某些内容时用作叠加层。 .cs文件

namespace VLC.WPF.Controls
{
    public class LoadingOverlay : ContentControl
    {
    }
}

.xaml文件

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:VLC.WPF.Controls">
    <Style TargetType="local:LoadingOverlay">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate>
                    <Grid>
                        <Grid Background="Black" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Opacity="0.8">
                            <ContentPresenter Content="{Binding OverlayContent}"/>
                        </Grid>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>

        </Setter>
    </Style>
</ResourceDictionary>

所有这些都将像这样使用

<UserControl.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="pack://application:,,,/../Controls/LoadingOverlay.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </UserControl.Resources>

    <controls:LoadingOverlay>
        <controls:LoadingOverlay.Resources>
            <Style TargetType="controls:LoadingOverlay">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding Path=RefreshNotifyTask.IsCompleted}" Value="True">
                        <Setter Property="Visibility" Value="Hidden"/>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </controls:LoadingOverlay.Resources>
            <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
                <TextBlock Foreground="White" FontSize="20" Text="Artikelen vernieuwen ..." />
                <Button x:Name="Cancel" Content="Annuleren"/>
            </StackPanel>
    </controls:LoadingOverlay>

在各种用户控件中,它运行正常但是看上去似乎没有加载。

这里有什么问题?代码看起来不错,所以我认为应该加载,但它不是。

3 个答案:

答案 0 :(得分:1)

您实际上覆盖了LoadingOverlay资源中的样式。

<Style TargetType="controls:LoadingOverlay">替换为以下<Style TargetType="{x:Type controls:LoadingOverlay}" BasedOn="{StaticResource {x:Type controls:LoadingOverlay}}">并瞧!

答案 1 :(得分:1)

在您的样式中尝试将TargetType添加到您的ControlTemplate中,如此

<ControlTemplate TargetType="local:LoadingOverlay">

我不明白为什么你在UserControl资源中设置样式而不使用Keys来引用ResourceDictionary中的样式。它可以使您的整体代码更加清晰,如果您以后必须稍作更改,则无需更改每个控件...例如:

<Style x:Key="overlayOne" TargetType="local:LoadingOverlay">
    <Setter Property="Template">
      <Setter.Value>
         <ControlTemplate TargetType="local:LoadingOverlay">
            <Grid>
              <Grid Background="Black" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Opacity="0.8">
                 <ContentPresenter Content="{Binding OverlayContent}"/>
              </Grid>
            </Grid>
         </ControlTemplate>
       </Setter.Value>
      </Setter>
    <Style.Triggers>
      <DataTrigger Binding="{Binding Path=RefreshNotifyTask.IsCompleted, RelativeSource={RelativeSource Self}} Value="True">
         <Setter Property="Visibility" Value="Hidden"/>
      </DataTrigger>
    </Style.Triggers>
</Style>

当您在页面中调用控件时

<local:LoadingOverlay Style="{DynamicResource overlayOne}">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
            <TextBlock Foreground="White" FontSize="20" Text="Artikelen vernieuwen ..." />
            <Button x:Name="Cancel" Content="Annuleren"/>
        </StackPanel>
</local:LoadingOverlay>

如果您发现需要更改另一个页面的样式,而不是为控件执行内联样式 - 在最初定义的样式之后尝试:

<Style x:Key="overlayTwo" TargetType="local:LoadingOverlay" BasedOn="{StaticResource overlayOne}">
     <Style.Triggers>
        <DataTrigger Binding="{Binding Path=RefreshNotifyTask.IsCompleted, RelativeSource={RelativeSource Self}} Value="True">
           <Setter Property="Background" Value="Green"/>
        </DataTrigger>
      </Style.Triggers>
</Style>

此样式使用您已定义的所有信息并添加另一个数据触发器,或者您可以覆盖其中的内容,更改样式中的其他元素,如字体大小或颜色。

然后,您只需在定义控件时使用此键

<local:LoadingOverlay Style="{DynamicResource overlayTwo}">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
            <TextBlock Foreground="White" FontSize="20" Text="Artikelen vernieuwen ..." />
            <Button x:Name="Cancel" Content="Annuleren"/>
        </StackPanel>
</local:LoadingOverlay>

很抱歉这个冗长的回答,但是如果你在不同的页面上有很多这些控件并且没有在ResourceDictionary中保留你所有的样式,我认为这是一个潜在的问题

P.S。如果你的内容是相同的,也可能是下面的风格的一部分

<Style x:Key="overlayOne" TargetType="local:LoadingOverlay">
    <Setter Property="Template">
      <Setter.Value>
         <ControlTemplate TargetType="local:LoadingOverlay">
            <Grid>
              <Grid Background="Black" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Opacity="0.8">
                 <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
            <TextBlock Foreground="White" FontSize="20" Text="Artikelen vernieuwen ..." />
            <Button x:Name="Cancel" Content="Annuleren"/>
        </StackPanel>
              </Grid>
            </Grid>
         </ControlTemplate>
       </Setter.Value>
      </Setter>
    <Style.Triggers>
      <DataTrigger Binding="{Binding Path=RefreshNotifyTask.IsCompleted, RelativeSource={RelativeSource Self}} Value="True">
         <Setter Property="Visibility" Value="Hidden"/>
      </DataTrigger>
    </Style.Triggers>
</Style>

然后你只需要在你的页面上

<local:LoadingOverlay Style="{DynamicResource overlayOne}"/>

答案 2 :(得分:0)

必须在将要使用它的UI元素之前定义资源。如果控件使用样式资源,则可视树中的样式必须更高。

将样式移动到UserControl资源

<UserControl.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="pack://application:,,,/../Controls/LoadingOverlay.xaml"/>
        </ResourceDictionary.MergedDictionaries>
        <Style TargetType="controls:LoadingOverlay">
            <Style.Triggers>
                <DataTrigger Binding="{Binding Path=RefreshNotifyTask.IsCompleted}" Value="True">
                    <Setter Property="Visibility" Value="Hidden"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </ResourceDictionary>
</UserControl.Resources>

<controls:LoadingOverlay>
    <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
        <TextBlock Foreground="White" FontSize="20" Text="Artikelen vernieuwen ..." />
        <Button x:Name="Cancel" Content="Annuleren"/>
    </StackPanel>
</controls:LoadingOverlay>