Как использовать выражение Blend 4 ranged property control

#silverlight #controls #expression-blend

#silverlight #элементы управления #выражение-blend

Вопрос:

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

Этот:

введите описание изображения здесь

Правки:

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

Ответ №1:

Некоторое время назад я предпринял попытку переделать палитру цветов в WPF, и мне понадобился аналогичный элемент управления для ввода значений 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 amp;amp; 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 amp;amp; 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 amp;amp; _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>
  

Ответ №2:

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

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

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

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