从 ContentControl 绑定前景 [英] Binding Foreground from ContentControl

查看:21
本文介绍了从 ContentControl 绑定前景的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用 WindowsPhone 8 和 ControlTemplate 时遇到了绑定问题.下面是一个例子:

I have a binding problem with WindowsPhone 8 and a ControlTemplate. Here is an example:

<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 中定义的前景红色".但没有任何作用...目标是在我的样式中更改 VisualState 中的 ContentContainer 前景.有人可以帮我吗?

I would like to use in my Button.Content the foreground "Red" I defined in the ContentContainer. But nothing works... The goal is to change the ContentContainer foreground in a VisualState in my Style. Can anyone help me?

推荐答案

设法通过行为实现了这一点.这是一个相当复杂的解决方案,但这是我发现的唯一一个工作:

Managed to pull this off with a behavior. It's a pretty complicated solution, but it's the only one i found working :

首先,一些实用的东西:

First, some Util stuff :

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

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

Now, let's define a behavior that does the binding :

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 中):

What this behavior does is bind the control's foreground to the foreground of the ContentControl found in the template of the specified parent. This is how you use it (in 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>

这篇关于从 ContentControl 绑定前景的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆