Как использовать элемент управления ранжирования Expression Blend 4 - PullRequest
1 голос
/ 11 мая 2011

Есть ли способ использовать отличный контроль ранжированных значений Expression Blend в ваших собственных проектах?

Вот этот:

enter image description here

редактирует:

Я бы очень, очень хотел бы знать.

Ответы [ 2 ]

1 голос
/ 26 мая 2011

Некоторое время назад в WPF я попытался переделать ColorPicker, и мне понадобился аналогичный элемент управления для ввода значений R, G, B и A.

ColorComponentSlider

Это не завершено, но дает довольно хорошее начало. Он поддерживает перетаскивание и ввод, но я выбрал другую схему перетаскивания, потому что мне не нравится перетаскивание Blend.

Вот что я сделал:

[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>
1 голос
/ 26 мая 2011

Этот элемент управления определен в сборке Microsoft.Expression.Framework, расположенной в C:\Program Files (x86)\Microsoft Expression\Blend 4\Microsoft.Expression.Framework.dll. Это называется NumberEditor.

Хотя вы, вероятно, могли бы использовать этот элемент управления, он тесно интегрирован с сеткой свойств Blend. Кроме того, вы не сможете распространять сборку.

Быстрый тест показал, что его использование не так интуитивно понятно, как вы ожидаете. Так что, вероятно, было бы лучше сделать свой собственный.

Кроме того, этот элемент управления создан для WPF, а не для Silverlight.

...