XAML 从ContentControl绑定前景

7gyucuyw  于 11个月前  发布在  其他
关注(0)|答案(3)|浏览(102)

我有一个WindowsPhone 8和ControlTemplate的绑定问题。下面是一个例子:

<UserControl.Resources>
<Style TargetType="Button">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Button">
                <ContentControl x:Name="ContentContainer" Foreground="Red" Content="{TemplateBinding Content}"/>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
</UserControl.Resources>

<Button>
    <Button.Content>
        <TextBlock Text="123"/>
    </Button.Content>
<Button>

字符串
我想在我的Button.Content中使用我在ContentContainer中定义的前景“Red”。但没有任何效果.目标是在我的Style中更改VisualState中的ContentContainer前景。有人能帮助我吗?

fslejnso

fslejnso1#

你应该做:

<Button Content="123"/>

字符串
而不是放一个文本块。
但是,如果你想保留文本块,你应该这样做:

<Style TargetType="TextBlock">
            <Setter Property="Foreground">
                <Setter.Value>
                    red
                </Setter.Value>
            </Setter>
        </Style>

0sgqnhkj

0sgqnhkj2#

这是一个相当复杂的解决方案,但它是我发现的唯一一个工作:
首先,一些Util的东西:

public static class IEnumerableExt
{
    public static T FirstOrDefault<T>(this IEnumerable<T> source)
    {
        if (source.Count() > 0)
            return source.ElementAt(0);
        return default(T);
    }
}

字符串
而且...

public static class DependencyObjectExt
{
        public static DependencyObject GetChild(this DependencyObject @this, int childIndex)
        {
            return VisualTreeHelper.GetChild(@this, childIndex);
        }

        public static IEnumerable<DependencyObject> GetChildren(this DependencyObject @this)
        {
            for(int i = 0; i < VisualTreeHelper.GetChildrenCount(@this); i++)
            {
                yield return @this.GetChild(i);
            }
        }

        public static IEnumerable<T> FindChildrenOfType<T>(this DependencyObject @this) where T : DependencyObject
        {
            foreach(var child in @this.GetChildren())
            {
                if(child is T)
                {
                    yield return child as T;
                }
            }
        }

        public static IEnumerable<T> FindDescendantsOfType<T>(this DependencyObject @this) where T : DependencyObject
        {
            IEnumerable<T> result = Enumerable.Empty<T>();

            foreach(var child in @this.GetChildren())
            {
                if(child is T)
                {
                    result = result.Concat(child.ToEnumerable().Cast<T>());
                }
                result = result.Concat(child.FindDescendantsOfType<T>());
            }

            return result;
        }
}


现在,让我们定义一个执行绑定的行为:

public class ContentControlForegroundBindingBehavior : Behavior<Control>
{
    public static DependencyProperty ParentProperty =
        DependencyProperty.Register("Parent", typeof(Control),
            typeof(ContentControlForegroundBindingBehavior), new PropertyMetadata(null));

    public Control Parent
    {
        get { return (Control)this.GetValue(ParentProperty); }
        set { this.SetValue(ParentProperty, value); }
    }

    protected override void OnAttached()
    {
        base.OnAttached();

        AssociatedObject.Loaded += (sender, e) =>
        {
            if (Parent == null) return;

            var control = AssociatedObject as Control;
            if (control == null) return;

            var contentControl = Parent.FindDescendantsOfType<ContentControl>().FirstOrDefault();
            if (contentControl == null) return;

            control.SetBinding(Control.ForegroundProperty, new Binding()
            {
                NotifyOnSourceUpdated = true,
                Mode = BindingMode.OneWay,
                UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,
                BindsDirectlyToSource = true,
                Path = new PropertyPath(Control.ForegroundProperty),
                Source = contentControl
            });
        };
    }
}


此行为所做的是将控件的前台绑定到指定父级模板中找到的ContentControl的前台。这是您如何使用它(在xaml中):

xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" 
        xmlns:behaviors=" ---------- Your Behaviors Namespace ---------"

<Button x:Name="SomeName"
                Width="125"
                Height="30"
                Click="OnButtonClick"
                HorizontalAlignment="Left"
                VerticalAlignment="Top"
                Margin="50,54,0,0">
            <Button.Content>
                <controls:IconText Icon="SomeIcon.png"
                                   Text="SomeText">
                    <i:Interaction.Behaviors>
                        <behaviors:ContentControlForegroundBindingBehavior Parent="{Binding ElementName=SomeName}"/>
                    </i:Interaction.Behaviors>
                </controls:IconText>
            </Button.Content>
</Button>

ewm0tg9j

ewm0tg9j3#

现在是2023年,Windows phone已经不存在了。我来到这里寻找WPF .NET的解决方案,当时没有找到解决方案。
既然我已经找到了一个解决方案(至少是WPF.NET的),我就把它贴在这里,以防其他人也像我一样来到这里寻找灵感。
解决方案是使用TextElement

  • ContentControl上设置TextElement.Foreground
  • Foreground上使用TemplateBinding

现在,前景色被绑定到ContentControl的内容。
以OP的代码为例:

<Style TargetType="Button">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Button">
                <ContentControl x:Name="ContentContainer" TextElement.Foreground="Red" Content="{TemplateBinding Content}"/>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
</UserControl.Resources>

<Button>
    <Button.Content>
        <TextBlock Text="123" Foreground="{TemplateBinding TextElement.Foreground}"/>
    </Button.Content>
<Button>```

字符串

相关问题