从ContentControl绑定前景

时间:2014-02-21 11:12:28

标签: c# xaml windows-phone-8

我对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前景。任何人都可以帮助我吗?

2 个答案:

答案 0 :(得分:0)

你应该这样做:

<Button Content="123"/>

而不是放置TextBlock。

但是如果你想保留TextBlock,你应该这样做:

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

答案 1 :(得分:0)

通过行为来管理这个问题。这是一个非常复杂的解决方案, 但它是我发现的唯一一个工作:

首先,一些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>