开发者

How to use the Expression Blend 4 ranged property control

Is there a way to use the nifty Expression Blend ranged value control i开发者_如何学Gon your own projects?

This one:

How to use the Expression Blend 4 ranged property control

Edits:

I would really, really love to know.


I made an attempt a while back in WPF to remake the ColorPicker and I needed a similar control to enter the R, G, B and A values.

How to use the Expression Blend 4 ranged property control

It's not complete but it gives a pretty good start. It supports dragging and typing but I picked a different dragging scheme because I dislike the Blend drag.

Here's what I did:

[TemplateVisualState(GroupName = "EditStates", Name = "DragMode")]
[TemplateVisualState(GroupName = "EditStates", Name = "TypeMode")]
public class ColorComponentSlider : Control
{
    static ColorComponentSlider()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(ColorComponentSlider), new FrameworkPropertyMetadata(typeof(ColorComponentSlider)));
    }

    private bool _isTemplateApplied = false;
    private TextBox _textBox;
    private TextBlock _textBlock;
    private GradientStop _gradientStart;
    private GradientStop _gradientEnd;
    private Grid _progressGrid;
    private bool _isDragging = false;

    public string Component
    {
        get { return (string)GetValue(ComponentProperty); }
        set { SetValue(ComponentProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Component.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ComponentProperty =
        DependencyProperty.Register("Component", typeof(string), typeof(ColorComponentSlider), new UIPropertyMetadata("R", OnComponentPropertyChanged));

    private static void OnComponentPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        var colorComponentSlider = sender as ColorComponentSlider;
        colorComponentSlider.UpdateChildControls();
    }

    public Color Color
    {
        get { return (Color)GetValue(ColorProperty); }
        set { SetValue(ColorProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Color.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ColorProperty =
        DependencyProperty.Register("Color", typeof(Color), typeof(ColorComponentSlider), new UIPropertyMetadata(Colors.Black, OnColorPropertyChanged));

    private static void OnColorPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        var colorComponentSlider = sender as ColorComponentSlider;
        colorComponentSlider.UpdateChildControls();
    }

    private void UpdateChildControls()
    {
        if (_isTemplateApplied)
        {
            double progress = 0;
            string colorComponent = String.Empty;
            var comp = Component.ToUpper();
            if (comp == "A")
            {
                _gradientStart.Color = Color.FromArgb(0, Color.R, Color.G, Color.B);
                _gradientEnd.Color = Color.FromArgb(255, Color.R, Color.G, Color.B);
                colorComponent = Color.A.ToString();
                progress = Color.A;
            }
            else if (comp == "R")
            {
                _gradientStart.Color = Color.FromArgb(Color.A, 0, Color.G, Color.B);
                _gradientEnd.Color = Color.FromArgb(Color.A, 255, Color.G, Color.B);
                colorComponent = Color.R.ToString();
                progress = Color.R;
            }
            else if (comp == "G")
            {
                _gradientStart.Color = Color.FromArgb(Color.A, Color.R, 0, Color.B);
                _gradientEnd.Color = Color.FromArgb(Color.A, Color.R, 255, Color.B);
                colorComponent = Color.G.ToString();
                progress = Color.G;
            }
            else if (comp == "B")
            {
                _gradientStart.Color = Color.FromArgb(Color.A, Color.R, Color.G, 0);
                _gradientEnd.Color = Color.FromArgb(Color.A, Color.R, Color.G, 255);
                colorComponent = Color.B.ToString();
                progress = Color.B;
            }
            if (colorComponent.Length > 0)
            {
                _textBlock.Text = colorComponent;
                _textBox.Text = colorComponent;
                _progressGrid.ColumnDefinitions[0].Width = new GridLength(progress, GridUnitType.Star);
                _progressGrid.ColumnDefinitions[1].Width = new GridLength(255 - progress, GridUnitType.Star);
            }
        }
    }

    private VisualStateGroup _editStates = null;
    private VisualState _dragModeState = null;
    private VisualState _typeModeState = null;

    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();

        _textBox = this.Template.FindName("textBox", this) as TextBox;
        _textBlock = this.Template.FindName("textBlock", this) as TextBlock;
        _gradientStart = this.Template.FindName("PART_GradientStart", this) as GradientStop;
        _gradientEnd = this.Template.FindName("PART_GradientEnd", this) as GradientStop;
        _progressGrid = this.Template.FindName("PART_Progress", this) as Grid;

        var root = this.Template.FindName("root", this) as FrameworkElement;
        var stateGroups = VisualStateManager.GetVisualStateGroups(root);
        for (int i = 0; i < stateGroups.Count; i++)
        {
            var stateGroup = stateGroups[i] as VisualStateGroup;
            if (stateGroup != null && stateGroup.Name == "EditStates")
            {
                _editStates = stateGroup;
                for (int s = 0; s < _editStates.States.Count; s++)
                {
                    var state = _editStates.States[s] as VisualState;
                    if (state.Name == "DragMode")
                    {
                        _dragModeState = state;
                    }
                    else if (state.Name == "TypeMode")
                    {
                        _typeModeState = state;
                    }
                }
                break;
            }
        }
        VisualStateManager.GoToState(this, _dragModeState.Name, false);
        _isTemplateApplied = true;
        UpdateChildControls();
    }

    private Point _mouseLeftButtonDownPreviousPosition;

    protected override void OnMouseLeftButtonDown(System.Windows.Input.MouseButtonEventArgs e)
    {
        base.OnMouseLeftButtonDown(e);
        if (_editStates.CurrentState == _dragModeState)
        {
            _mouseLeftButtonDownPreviousPosition = e.GetPosition(this);
            Mouse.Capture(this);
        }
    }

    protected override void OnMouseMove(MouseEventArgs e)
    {
        base.OnMouseMove(e);
        if (_editStates.CurrentState == _dragModeState && e.LeftButton == MouseButtonState.Pressed)
        {
            _isDragging = true;
            var position = e.GetPosition(this);

            int offset = (int)(_mouseLeftButtonDownPreviousPosition.Y - position.Y);

            string comp = Component.ToUpper();

            if (comp == "A")
            {
                int v;
                if (Color.A + offset < 0)
                {
                    v = 0;
                }
                else if (Color.A + offset > 255)
                {
                    v = 255;
                }
                else
                {
                    v = Color.A + offset;
                }
                Color = Color.FromArgb((byte)v, Color.R, Color.G, Color.B);
            }
            else if (comp == "R")
            {
                int v;
                if (Color.R + offset < 0)
                {
                    v = 0;
                }
                else if (Color.R + offset > 255)
                {
                    v = 255;
                }
                else
                {
                    v = Color.R + offset;
                }
                Color = Color.FromArgb(Color.A, (byte)v, Color.G, Color.B);
            }
            else if (comp == "G")
            {
                int v;
                if (Color.G + offset < 0)
                {
                    v = 0;
                }
                else if (Color.G + offset > 255)
                {
                    v = 255;
                }
                else
                {
                    v = Color.G + offset;
                }
                Color = Color.FromArgb(Color.A, Color.R, (byte)v, Color.B);
            }
            else if (comp == "B")
            {
                int v;
                if (Color.B + offset < 0)
                {
                    v = 0;
                }
                else if (Color.B + offset > 255)
                {
                    v = 255;
                }
                else
                {
                    v = Color.B + offset;
                }
                Color = Color.FromArgb(Color.A, Color.R, Color.G, (byte)v);
            }

            _mouseLeftButtonDownPreviousPosition = position;
        }
        else
        {
            _isDragging = false;
        }

    }
    protected override void OnMouseLeftButtonUp(System.Windows.Input.MouseButtonEventArgs e)
    {
        base.OnMouseLeftButtonUp(e);
        if (_editStates.CurrentState == _dragModeState)
        {
            var position = e.GetPosition(this);
            Mouse.Capture(null);
            if (!_isDragging && _mouseLeftButtonDownPreviousPosition == position)
            {
                VisualStateManager.GoToState(this, _typeModeState.Name, true);
                _textBox.SelectAll();
            }
            _isDragging = false;
        }
    }

    protected override void OnGotKeyboardFocus(System.Windows.Input.KeyboardFocusChangedEventArgs e)
    {
        base.OnGotKeyboardFocus(e);
        if (_editStates.CurrentState == _dragModeState)
        {
            VisualStateManager.GoToState(this, _typeModeState.Name, true);
        }
    }

    protected override void OnLostKeyboardFocus(System.Windows.Input.KeyboardFocusChangedEventArgs e)
    {
        base.OnLostKeyboardFocus(e);
        if (_editStates.CurrentState == _typeModeState)
        {
            VisualStateManager.GoToState(this, _dragModeState.Name, true);

            byte v;
            if (Byte.TryParse(_textBox.Text, out v))
            {
                string comp = Component.ToUpper();

                if (comp == "A")
                {
                    Color = Color.FromArgb((byte)v, Color.R, Color.G, Color.B);
                }
                else if (comp == "R")
                {
                    Color = Color.FromArgb(Color.A, (byte)v, Color.G, Color.B);
                }
                else if (comp == "G")
                {
                    Color = Color.FromArgb(Color.A, Color.R, (byte)v, Color.B);
                }
                else if (comp == "B")
                {
                    Color = Color.FromArgb(Color.A, Color.R, Color.G, (byte)v);
                }
            }
        }
    }
}

XAML:

<Style BasedOn="{x:Null}"
       TargetType="{x:Type local:ColorComponentSlider}">
    <Setter Property="Foreground"
            Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" />
    <Setter Property="Background"
            Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}" />
    <Setter Property="BorderBrush"
            Value="Black" />
    <Setter Property="BorderThickness"
            Value="1" />
    <Setter Property="Padding"
            Value="1" />
    <Setter Property="AllowDrop"
            Value="true" />
    <Setter Property="FocusVisualStyle"
            Value="{x:Null}" />
    <Setter Property="Focusable"
            Value="True" />
    <Setter Property="ScrollViewer.PanningMode"
            Value="VerticalFirst" />
    <Setter Property="Stylus.IsFlicksEnabled"
            Value="False" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:ColorComponentSlider}">
                <Border x:Name="root"
                        BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}"
                        Background="{TemplateBinding Background}"
                        SnapsToDevicePixels="true"
                        CornerRadius="5"
                        ClipToBounds="True">
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="EditStates">
                            <VisualState x:Name="DragMode" />
                            <VisualState x:Name="TypeMode">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
                                                                   Storyboard.TargetName="textBlock">
                                        <DiscreteObjectKeyFrame KeyTime="0"
                                                                Value="{x:Static Visibility.Hidden}" />
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)"
                                                                   Storyboard.TargetName="textBox">
                                        <DiscreteObjectKeyFrame KeyTime="0"
                                                                Value="{x:Static Visibility.Visible}" />
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="auto" />
                            <RowDefinition Height="*" MinHeight="5" />
                        </Grid.RowDefinitions>
                        <Grid  x:Name="PART_Progress"
                               UseLayoutRounding="True"
                               RenderOptions.EdgeMode="Unspecified">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="*" />
                                <ColumnDefinition Width="*" />
                            </Grid.ColumnDefinitions>
                            <Border CornerRadius="3,3,0,0"
                                    Background="#FF666666" />
                        </Grid>
                        <TextBlock x:Name="textBlock"
                                   Background="{x:Null}"
                                   Foreground="{TemplateBinding Foreground}"
                                   Margin="0"
                                   Padding="2,2,0,0" />
                        <TextBox x:Name="textBox"
                                 Background="{x:Null}"
                                 BorderThickness="0"
                                 CaretBrush="{TemplateBinding Foreground}"
                                 Foreground="{TemplateBinding Foreground}"
                                 Margin="0"
                                 Padding="0,2,0,0"
                                 Visibility="Hidden" />
                        <Border Grid.Row="1"
                                CornerRadius="0,0,3,3">
                            <Border.Background>
                                <DrawingBrush TileMode="Tile"
                                              Viewport="0,0,10,10"
                                              ViewportUnits="Absolute">
                                    <DrawingBrush.Drawing>
                                        <DrawingGroup>
                                            <GeometryDrawing Brush="White">
                                                <GeometryDrawing.Geometry>
                                                    <RectangleGeometry Rect="0,0,10,10" />
                                                </GeometryDrawing.Geometry>
                                            </GeometryDrawing>
                                            <GeometryDrawing Brush="Silver">
                                                <GeometryDrawing.Geometry>
                                                    <GeometryGroup>
                                                        <RectangleGeometry Rect="0,0,5,5" />
                                                        <RectangleGeometry Rect="5,5,5,5" />
                                                    </GeometryGroup>
                                                </GeometryDrawing.Geometry>
                                            </GeometryDrawing>
                                        </DrawingGroup>
                                    </DrawingBrush.Drawing>
                                </DrawingBrush>
                            </Border.Background>
                        </Border>
                        <Border Grid.Row="1"
                                CornerRadius="0,0,3,3"
                                BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="0,1,0,0">
                            <Border.Background>
                                <LinearGradientBrush EndPoint="1,0.5"
                                                     StartPoint="0,0.5">
                                    <GradientStop x:Name="PART_GradientStart"
                                                  Offset="0"
                                                  Color="#00000000" />
                                    <GradientStop x:Name="PART_GradientEnd"
                                                  Offset="1"
                                                  Color="#FFFFFFFF" />
                                </LinearGradientBrush>
                            </Border.Background>
                        </Border>
                    </Grid>

                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsEnabled"
                             Value="false">
                        <Setter Property="Background"
                                TargetName="root"
                                Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" />
                        <Setter Property="Foreground"
                                Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" />
                    </Trigger>
                    <Trigger SourceName="textBox"
                             Property="Visibility"
                             Value="Visible">
                        <Setter TargetName="textBox"
                                Property="FocusManager.FocusedElement"
                                Value="{Binding ElementName=textBox}" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>


This control is defined in the Microsoft.Expression.Framework assembly, located at C:\Program Files (x86)\Microsoft Expression\Blend 4\Microsoft.Expression.Framework.dll. It is called the NumberEditor.

While you probably could use this control, it is tightly integrated with the Blend property grid. In addition, you wouldn't be allowed to distribute the assembly.

A quick test showed, it's not as intuitive to use as you'd expect. So it would probably be best to roll your own.

Also, this control is built for WPF, not Silverlight.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜