为什么我的WPF绑定在状态更改中不起作用?

时间:2011-07-15 15:49:49

标签: binding

我在WrapPanel中有一些项目。我希望能够点击一个项目并让它扩展到包装面板的整个宽度。我尝试通过在用于每个项目的控件中创建两个状态Expanded和Colapsed来完成此操作。对于Expanded状态,我将控件的Width限制为等于WrapPanel的ActualWidth。

当我没有得到我期望的结果时,我尝试将Expanded值设置为特定数字(而不是绑定)。那很有效。这些项目在两个Colapsed和Exapanded宽度之间切换。我仍然希望Expanded状态等于WrapPanel的宽度,而不是任意固定宽度。我知道我的绑定有效,因为如果我只是直接绑定Width属性(而不是通过视觉状态),WrapPanel中的项目与其宽度匹配。

带有绑定的扩展状态 - 不起作用:

<VisualState x:Name="Expanded">
<Storyboard>
    <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Width)" Storyboard.TargetName="JobMaster">
        <EasingDoubleKeyFrame KeyTime="0">
            <EasingDoubleKeyFrame.Value>
                 <Binding 
                   Path="ActualWidth"
                   RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type WrapPanel}}" />
            </EasingDoubleKeyFrame.Value>
        </EasingDoubleKeyFrame>
    </DoubleAnimationUsingKeyFrames>
</Storyboard>

具有硬编码值的扩展状态 - 工作

<VisualState x:Name="Expanded">
<Storyboard>
    <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Width)" Storyboard.TargetName="JobMaster">
        <EasingDoubleKeyFrame KeyTime="0" Value="800" />
    </DoubleAnimationUsingKeyFrames>
</Storyboard>

绑定控件Width属性直接工作

<UserControl.Width>
       <Binding 
       Path="ActualWidth"
       RelativeSource="{RelativeSource AncestorType={x:Type WrapPanel}}" />
</UserControl.Width>

那么为什么状态中的绑定不起作用还是有其他方法可以做到这一点?

2 个答案:

答案 0 :(得分:1)

我无法使用视觉状态来实现这一点。相反,我写了一个行为。

public class TileExpandColapseBehavoir : Behavior<Control>
{
    private ITile _data;

    #region Properties

    public static readonly DependencyProperty TileControlProperty = DependencyProperty.Register("TileControl", typeof(object), typeof(TileExpandColapseBehavoir), new PropertyMetadata(null));
    public static readonly DependencyProperty DefaultWidthProperty = DependencyProperty.Register("DefaultWidth", typeof(Double), typeof(TileExpandColapseBehavoir), new PropertyMetadata(null));

    public object TileControl
    {
        get { return (object)this.GetValue(TileControlProperty); }
        set { this.SetValue(TileControlProperty, value); }
    }

    public double DefaultWidth
    {
        get { return (double)this.GetValue(DefaultWidthProperty); }
        set { this.SetValue(DefaultWidthProperty, value); }
    }

    #endregion

    public TileExpandColapseBehavoir()
    {
    }

    protected override void OnAttached()
    {
        this.AssociatedObject.PreviewMouseDown +=new MouseButtonEventHandler(AssociatedObject_MouseUp);  
    }

    private void AssociatedObject_MouseUp(object sender, MouseButtonEventArgs e)
    {
        UIElement child = (UIElement)sender;
        WrapPanel parentWrap = FindAncestorUtil.TryFindAcestor<WrapPanel>(child);
        if (parentWrap != null && TileControl is UserControl)
        {
            GetData();
            if (_data.IsExpanded == false)
            {
                Binding newBinding = new Binding();
                newBinding.Source = parentWrap;
                newBinding.Path = new PropertyPath("ActualWidth");

                UserControl thisTile = (UserControl)TileControl;
                BindingOperations.SetBinding(thisTile, UserControl.WidthProperty, newBinding);
                _data.IsExpanded = true;
            }
            else
            {
                UserControl thisTile = (UserControl)TileControl;

                BindingOperations.ClearBinding(thisTile, UserControl.WidthProperty);
                thisTile.Width = DefaultWidth;
                _data.IsExpanded = false;
            }
        }
    }

    private void GetData()
    {
        if (_data == null && AssociatedObject.DataContext is ITile)
        {  
             _data = (ITile)AssociatedObject.DataContext;
        }
    }
}

答案 1 :(得分:0)

您的RelativeSource绑定正在寻找动画的祖先,而不是动画的目标。尝试给你的WrapPanel一个名字,然后使用Element绑定。

<Binding Path="ActualWidth" ElementName="MyWrapPanel"/>