本文介绍了从 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 绑定前景的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-22 16:03