WPF样式属性设置器不适用于所有类型

时间:2011-03-10 00:47:35

标签: wpf properties user-controls triggers styles

我多次阅读了关于Style s,Style.TriggerProperty-Setters的说明,但是如果这些风格的应用与否,我仍然是完全随机的。

在以下示例中,Canvas将变为白色,但Path根本不受影响:

<UserControl x:Class="Still.Tooll.CurveEditPoint"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:Still.Tooll"
             >
    <UserControl.Style>
        <Style>
            <Style.Triggers>
                <Trigger Property="local:CurveEditPoint.IsSelected" Value="true">
                    <Setter Property="Path.Stroke" Value="#fff"/>
                    <Setter Property="Canvas.Background" Value="#fff"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </UserControl.Style>
    <Canvas>
        <Path StrokeThickness="0.5" Data="M 0, 0 L 40,20"/>  
    </Canvas>
</UserControl>

我想这需要对PathCanvas的嵌套做一些事情,但是再次,必须有一种方法来设置控件的子元素的样式。

我必须承认,来自HTML / CSS,我发现WPF样式不必要地困难!任何要点或解释都欢迎!

感谢, 汤姆

3 个答案:

答案 0 :(得分:2)

您无法以这种方式访问​​UserControl的可视元素。 Style只能在UserControl上设置属性。因此,您的第一个setter(“Path.Stroke”)将在您的UserControl上查找名为Path的属性,然后设置它的Stroke。它不会将其应用于UserControl中的所有路径或您在下面定义的路径。

未设置Canvas的背景。正在设置UserControl的背景,并且画布将继续没有背景。 setter在UserControl上工作的原因是因为Canvas.BackgroundPropertyUserControl.BackgroundProperty是相同的依赖属性(即使它们是不同的所有者)。

我建议在UserControl上公开依赖项属性,这些属性由Style更改并由元素绑定。这样的东西(它重用了Background / Foreground属性):

<UserControl x:Name="userControl" x:Class="Still.Tooll.CurveEditPoint"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:local="clr-namespace:Still.Tooll"
         >

    <UserControl.Style>
        <Style>
            <Style.Triggers>
                <Trigger Property="local:CurveEditPoint.IsSelected" Value="true">
                    <Setter Property="Foreground" Value="#fff"/>
                    <Setter Property="Background" Value="#fff"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </UserControl.Style>

    <Canvas>
        <Path Stroke="{Binding Element=userControl, Path=Foreground}" StrokeThickness="0.5" Data="M 0, 0 L 40,20"/>  
    </Canvas>
</UserControl>

答案 1 :(得分:0)

如果您在UserControl上将Style定义为Resource,然后将其应用于可能有效的每个元素:

<UserControl x:Class="Still.Tooll.CurveEditPoint"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:local="clr-namespace:Still.Tooll"
         >

<UserControl.Resources>

    <Style x:Key="style">
        <Style.Triggers>
            <Trigger Property="local:CurveEditPoint.IsSelected" Value="true">
                <Setter Property="Path.Stroke" Value="#fff"/>
                <Setter Property="Canvas.Background" Value="#fff"/>
            </Trigger>
        </Style.Triggers>
    </Style>
</UserControl.Resources>

<Canvas Style="{StaticResource style}">
    <Path StrokeThickness="0.5"   Data="M 0, 0 L 40,20" Style="{StaticResource style}"/>
</Canvas>

答案 2 :(得分:0)

虽然不是通过风格,但这是一个解决方法,我曾经在我的应用程序中实现这一点。

* Visual Children Finder *

    /// <summary>
    /// This function iterates through the visual tree and returns the child item of the type child item.
    /// </summary>
    /// <typeparam name="childItem"></typeparam>
    /// <param name="obj"></param>
    /// <returns></returns>
    public static TChild FindVisualChild<TChild>(DependencyObject obj)
        where TChild : DependencyObject
    {
        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
        {
            DependencyObject child = VisualTreeHelper.GetChild(obj, i);

            if (child != null && child is TChild)
            {
                return (TChild)child;
            }
            else
            {
                TChild childOfChild = FindVisualChild<TChild>(child);

                if (childOfChild != null)
                {
                    return childOfChild;
                }
            }
        }

        return null;
    }

在背后的某些代码中使用它,例如 - ListBox deviceImagesListBox = UtilityFunctions.FindVisualChild<RealisticListBox>(selectedRoomListBox);

现在您已拥有控件,您可以在Code Behind中使用它。我同意我们应该在XAML中使用STYLE寻找能够实现这一点的东西