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

发布于 2024-10-21 06:57:04 字数 1391 浏览 1 评论 0原文

我多次阅读了有关 StyleStyle.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>

我猜这与 的嵌套有关Canvas 内的 >Path,但话又说回来,必须有一种方法来设置控件的子元素的样式。

我不得不承认,从 HTML/CSS 开始,我发现 WPF 样式不必要地困难!欢迎任何观点或解释!

谢谢, 汤姆

I read the description on Styles, Style.Triggers andProperty-Setters several times, but I still, if the styles are applied or not seem to be completely random.

In the following example, the Canvas will turn white, the Path, however, is not affected at all:

<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>

I guess this has to do something with the nesting of the Path inside the Canvas, but then again, there must be a way to style sub elements of a control.

I have to admit, that coming from HTML/CSS, I find the WPF styling unnecessarily difficult! Any points or explanations welcome!

thanks,
tom

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

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

发布评论

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

评论(3

溺ぐ爱和你が 2024-10-28 06:57:04

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

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

我建议在您的 UserControl 上公开依赖属性,这些属性由您的样式更改并由您的元素绑定。像这样的东西(重用背景/前景属性):

<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>

You cannot access the visual elements of the UserControl in that manner. The Style can only set properties on the UserControl. So your first setter ("Path.Stroke") will look for a property on your UserControl named Path, and then set it's Stroke. It doesn't apply it to all Paths in your UserControl or the one you have defined below.

The Canvas's Background is not being set. The background of the UserControl is being set, and the canvas will continue to have no background. The reason the setter works on the UserControl is because the Canvas.BackgroundProperty and UserControl.BackgroundProperty are the same dependency property (even though they are different owners).

I'd recommend exposing dependency properties on your UserControl, which are changed by your Style and bound to by your elements. Something like this (which reuses the Background/Foreground properties):

<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>
放肆 2024-10-28 06:57:04

虽然不是通过风格,但这是我用来在我的应用程序中实现这一目标的解决方法。

*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(selectedRoomListBox);

现在您拥有了控件,您可以使用它它在代码隐藏中。我同意我们应该寻找一些东西来使用 XAML 中的 STYLE 来实现这一目标

Though not through style but here is a workaround that i used to achieve this thing in my app.

*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;
    }

Use it in some code behind like - ListBox deviceImagesListBox = UtilityFunctions.FindVisualChild<RealisticListBox>(selectedRoomListBox);

Now you have the control and you can play with it in Code Behind. I agree we should look for something to acheive this using STYLE in XAML

半枫 2024-10-28 06:57:04

如果您将 Style 定义为 UserControl 上的 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>

If you define the Style as a Resourceon the UserControl and then apply it to each of the elements it might work:

<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>

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