开发者

Why is my WPF binding not working in state change?

开发者 https://www.devze.com 2023-03-21 01:31 出处:网络
I have some items in a WrapPanel.I want to be able to click on an item and have it expand to the full width of the wrap panel.I tried doing this by creating two states, Expanded and Colapsed, in the c

I have some items in a WrapPanel. I want to be able to click on an item and have it expand to the full width of the wrap panel. I tried doing this by creating two states, Expanded and Colapsed, in the control that is used for each item. For the Expanded state, I bound the Width of the control to be equal to the ActualWidth of the WrapPanel.

When I didn't get the result I expected, I tried setting Expanded value to a specific number (instead of the the binding). That is working. The items toggle between the two Colapsed and Exapanded widths. I still want to have the Expanded state be equal to the width of the WrapPanel though, not an arbitrary fixed width. I know my binding works because if I just bind the Width property directly (not via visual states), the items in the WrapPanel match its width.

Expanded state with Binding - Doesn't work:

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

Expanded State with hard coded value - Works

<VisualState x:Name="Expanded">
<Storyboard>
    <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Width)" Storyboard.TargetName="JobMaste开发者_如何学编程r">
        <EasingDoubleKeyFrame KeyTime="0" Value="800" />
    </DoubleAnimationUsingKeyFrames>
</Storyboard>

Bind the control Width property directly works

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

So why doesn't the Binding in the state work or is there another way to do this?


I was never able to get this working using visual states. Instead I wrote a behavoir.

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


Your RelativeSource binding is looking for an ancestor of the animation, not the target of the animation. Try giving your WrapPanel a name and use Element binding instead.

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

精彩评论

暂无评论...
验证码 换一张
取 消