2

CodeBehind で VisualStatesを定義する(切り替えない)ことは可能ですか?

でいくつかの長方形を描画する Adorner を作成していOnRenderます。私がやりたいのは、これらの Rectangles の不透明度をプロパティIsMouseOver(0.3 から 0.8 など) で変更することです。

ビジュアル ツリーを持つ任意のコントロールでは、いくつかの VisualStates を追加し、DataStateBehavior でそれらを切り替えます。Adorner を使用してこれを行うにはどうすればよいですか?

4

3 に答える 3

4

これは完全に可能です。

誰かがここに興味を持っているなら、私がやった方法は次のとおりです。

public class MyAdorner: Adorner
{
    ctor (...):base(...)
    {
        ...

        var storyboard = new Storyboard();
        var doubleAnimation = new DoubleAnimation(0.2,new Duration(TimeSpan.Zero));
        Storyboard.SetTarget(doubleAnimation,this);
        Storyboard.SetTargetProperty(doubleAnimation,new PropertyPath(RectOpacityProperty));
        storyboard.Children.Add(doubleAnimation);

        var storyboard2 = new Storyboard();
        var doubleAnimation2 = new DoubleAnimation(0.5, new Duration(TimeSpan.Zero));
        Storyboard.SetTarget(doubleAnimation2, this);
        Storyboard.SetTargetProperty(doubleAnimation2, new PropertyPath(RectOpacityProperty));
        storyboard2.Children.Add(doubleAnimation2);

        var stateGroup = new VisualStateGroup { Name = "MouseOverState" };
        stateGroup.States.Add(new VisualState { Name = "MouseOut", Storyboard = storyboard });
        stateGroup.States.Add(new VisualState { Name = "MouseOver", Storyboard = storyboard2});

        var sgs = VisualStateManager.GetVisualStateGroups(this);
        sgs.Add(stateGroup);

        var dsb = new DataStateBehavior
            {
                Value = true,
                FalseState = "MouseOut",
                TrueState = "MouseOver"
            };
        BindingOperations.SetBinding(dsb, DataStateBehavior.BindingProperty, new Binding {Source = this, Path = new PropertyPath(IsMouseOverProperty)});
        dsb.Attach(this);

    }

    protected override void OnRender(DrawingContext drawingContext)
    {
        drawingContext.DrawRectangle(_mouseOverBrush, _pen, _rects[i]);     //mouseoverbrush is a Solidcolorbrush       
    }

    public double RectOpacity
    {
        get { return (double)GetValue(RectOpacityProperty); }
        set { SetValue(RectOpacityProperty, value); }
    }

    public static readonly DependencyProperty RectOpacityProperty =
        DependencyProperty.Register("RectOpacity", typeof(double), typeof(XmlNodeWrapperAdorner), new FrameworkPropertyMetadata(0.0,FrameworkPropertyMetadataOptions.AffectsRender,(o, args) =>
            {
                var adorner = o as MyAdorner;
                adorner._mouseOverBrush.Color = Color.FromArgb((byte)((double)args.NewValue * 0xFF), 0xFF, 0xBE, 0x00);
            }));

}

実際にはかなり簡単です。

ここでの重要なポイントは次のとおりです。

  • VisualStateGroups 添付プロパティを設定することはできません。コレクションを取得してから、独自のグループを追加する必要があります

  • new DataStateBehavior{Binding = new Binding(...){...}}これにより、プロパティに値が割り当てられないため、実行できません。派生していないため、クラスを使用することもできませんが、使用する必要があります。Behvior<T>FrameworkElementSetBindingBindingOperations

  • プロパティが変更されたときの自動再レンダリングのために、設定することに注意してFrameworkPropertyMetadataOptions.AffectsRenderください。

于 2011-04-03T21:07:55.057 に答える
0

コードに状態を追加できる場合、Blend などのツールは、可能なすべての構成ですべてのコードを実行して、どの状態が存在するか/可能であるかを調べる必要があります。

いいえ、コードでこれを行うことはできません。属性を使用してのみ可能です。

編集

私は修正されたままですが、言及された問題はまだ残っています。この手法は、設計者には役に立ちません。

于 2011-04-03T16:15:30.817 に答える
0

独自の動作でカスタム アドナーを既に作成しているので、アドナーの MouseOver メソッドをオーバーライドし、そこで四角形の不透明度を変更することをお勧めします...

別の方法は、独自の PropertyChanged イベントをリッスンして IsMouseOver の変化を監視するか、MouseMove イベントを監視することです...

于 2011-04-03T16:45:49.350 に答える