自定义事件触发器

时间:2018-01-23 17:00:34

标签: c# wpf

我有自定义范围滑块,工作正常,但我想更改文本框的颜色,这是我的XAML:

<UserControl x:Class="Slider.RangeSlider"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:Slider"
             mc:Ignorable="d" 
             x:Name="root"
             >    
<UserControl.Resources>
    <ControlTemplate x:Key="simpleSlider" TargetType="{x:Type Slider}">
        <Border SnapsToDevicePixels="true" 
                BorderBrush="{TemplateBinding BorderBrush}" 
                BorderThickness="{TemplateBinding BorderThickness}">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"/>
                    <RowDefinition Height="Auto" MinHeight="{TemplateBinding MinHeight}"/>
                    <RowDefinition Height="Auto"/>
                </Grid.RowDefinitions>
                <Rectangle x:Name="PART_SelectionRange"/>
                <Track x:Name="PART_Track" Grid.Row="1">
                    <Track.Thumb>
                        <Thumb x:Name="Thumb">
                            <Thumb.Template>
                                <ControlTemplate TargetType="Thumb">
                                    <Rectangle Fill="#C0C0C0" 
                                               Stroke="Black"
                                               StrokeThickness="1" 
                                               Width="10"
                                               Height="18"
                                               SnapsToDevicePixels="True"/>
                                </ControlTemplate>
                            </Thumb.Template>
                        </Thumb>
                    </Track.Thumb>
                </Track>
            </Grid>
        </Border>            
    </ControlTemplate>
</UserControl.Resources>
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition/>
        <RowDefinition/>
    </Grid.RowDefinitions>
    <Border BorderThickness="0,0,0,0" 
            BorderBrush="White" 
            VerticalAlignment="Center" 
            Height="1" 
            Margin="5,0,5,0"/>
    <Rectangle Grid.Row="0" VerticalAlignment="Center" Fill="#FFF78A09" Height="5" MaxHeight="5" Margin="10,0,20,0"/>
    <Slider x:Name="LowerSlider" Minimum="1" Grid.Row="1" 
            Maximum="12" 
            Value="{Binding LowerValue, ElementName=root}" IsSnapToTickEnabled="True" TickPlacement="Both" 
            Ticks="1,2,3,4,5,6,7,8,9,10,11,12" Template="{StaticResource simpleSlider}"
            Margin="10,0,20,0"/>
    <Slider x:Name="UpperSlider" Grid.Row="0" Thumb.DragCompleted="Thumb_Complete"
            Minimum="1"
            Maximum="12"
            Value="{Binding UpperValue, ElementName=root}" IsSnapToTickEnabled="True" TickPlacement="Both" 
            Ticks="1,2,3,4,5,6,7,8,9 10,11,12" Template="{StaticResource simpleSlider}"
            Margin="10,0,20,0"/>
    <StackPanel Grid.Row="2" Orientation="Horizontal">
        <TextBox Name="Month1" Text="Jan" Width="30" Margin="1.6,0,0,0" Background="{x:Null}" Foreground="#FFF78A09" FontFamily="Tahoma" BorderBrush="#FFF78A09" IsReadOnly="True" SelectionBrush="{x:Null}" />
        <TextBox Name="Month2" Text="Feb" Width="30" Margin="2,0,0,0" Background="{x:Null}" Foreground="#FFF78A09" FontFamily="Tahoma" BorderBrush="#FFF78A09" IsReadOnly="True" SelectionBrush="{x:Null}" />
        <TextBox Name="Month3" Text="Mar" Width="30" Margin="2,0,0,0" Background="{x:Null}" Foreground="#FFF78A09" FontFamily="Tahoma" BorderBrush="#FFF78A09" IsReadOnly="True" SelectionBrush="{x:Null}" />
        <TextBox Name="Month4" Text="Apr" Width="30" Margin="2,0,0,0" Background="{x:Null}" Foreground="#FFF78A09" FontFamily="Tahoma" BorderBrush="#FFF78A09" IsReadOnly="True" SelectionBrush="{x:Null}"/>
        <TextBox Name="Month5" Text="May" Width="30" Margin="2,0,0,0" Background="{x:Null}" Foreground="#FFF78A09" FontFamily="Tahoma" BorderBrush="#FFF78A09" IsReadOnly="True" SelectionBrush="{x:Null}"/>
        <TextBox Name="Month6" Text="Jun" Width="30" Margin="2,0,0,0" Background="{x:Null}" Foreground="#FFF78A09" FontFamily="Tahoma" BorderBrush="#FFF78A09" IsReadOnly="True" SelectionBrush="{x:Null}" />
        <TextBox Name="Month7" Text="Jul" Width="30" Margin="2,0,0,0" Background="{x:Null}" Foreground="#FFF78A09" FontFamily="Tahoma" BorderBrush="#FFF78A09" IsReadOnly="True" SelectionBrush="{x:Null}"/>
        <TextBox Name="Month8" Text="Aug" Width="30" Margin="2,0,0,0" Background="{x:Null}" Foreground="#FFF78A09" FontFamily="Tahoma" BorderBrush="#FFF78A09" IsReadOnly="True" SelectionBrush="{x:Null}"/>
        <TextBox Name="Month9" Text="Sep" Width="30" Margin="2,0,0,0" Background="{x:Null}" Foreground="#FFF78A09" FontFamily="Tahoma" BorderBrush="#FFF78A09" IsReadOnly="True" SelectionBrush="{x:Null}" />
        <TextBox Name="Month10" Text="Oct" Width="30" Margin="2,0,0,0" Background="{x:Null}" Foreground="#FFF78A09" FontFamily="Tahoma" BorderBrush="#FFF78A09" IsReadOnly="True" SelectionBrush="{x:Null}"/>
        <TextBox Name="Month11" Text="Nov" Width="30" Margin="2,0,0,0" Background="{x:Null}" Foreground="#FFF78A09" FontFamily="Tahoma" BorderBrush="#FFF78A09" IsReadOnly="True" SelectionBrush="{x:Null}" />
        <TextBox Name="Month12" Text="Dec" Width="30" Margin="2,0,0,0" Background="{x:Null}" Foreground="#FFF78A09" FontFamily="Tahoma" BorderBrush="#FFF78A09" IsReadOnly="True" SelectionBrush="{x:Null}" />
    </StackPanel>
</Grid>

以下是C#代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace Slider
{
    /// <summary>
    /// Interaction logic for UserControl1.xaml
    /// </summary>
    public partial class RangeSlider : UserControl
    {
        public RangeSlider()
        {
            InitializeComponent();
        }

        public RoutedEventHandler Custom_Complete;
        private void Thumb_Complete(object sender,RoutedEventArgs e)
        {
            if (Custom_Complete !=null)
            {
                Custom_Complete(this, new RoutedEventArgs());
            }
        }

        #region Setting dependancies
        public double Minimum
        {
            get { return (double)GetValue(MinimumProperty); }
            set { SetValue(MinimumProperty, value); }
        }

        public static readonly DependencyProperty MinimumProperty =
            DependencyProperty.Register("Minimum", typeof(double), typeof(RangeSlider), new UIPropertyMetadata(0d));

        public double LowerValue
        {
            get { return (double)GetValue(LowerValueProperty); }
            set { SetValue(LowerValueProperty, value); }
        }

        public static readonly DependencyProperty LowerValueProperty =
            DependencyProperty.Register("LowerValue", typeof(double), typeof(RangeSlider), new UIPropertyMetadata(0d));

        public double UpperValue
        {
            get { return (double)GetValue(UpperValueProperty); }
            set { SetValue(UpperValueProperty, value); }
        }

        public static readonly DependencyProperty UpperValueProperty =
            DependencyProperty.Register("UpperValue", typeof(double), typeof(RangeSlider), new UIPropertyMetadata(0d));

        public double Maximum
        {
            get { return (double)GetValue(MaximumProperty); }
            set { SetValue(MaximumProperty, value); }
        }

        public static readonly DependencyProperty MaximumProperty =
            DependencyProperty.Register("Maximum", typeof(double), typeof(RangeSlider), new UIPropertyMetadata(1d));

        #endregion
    }
}

我想要做的是每次MouseUp发生时设置一个事件,以便它检查UpperSlider&amp;的值。 LowerSlider如果滑块不在范围内,则会将每个文本框的边框颜色从橙色更改为灰色。

有人可以帮忙吗?

1 个答案:

答案 0 :(得分:0)

首先,您的RangeSlider处理数字范围,因此我认为将月份指标放在 UserControl中是不合理的。我会分开分开。

首先,使用StackPanel Xaml中的文本框删除RangeSlider。创建一个新的DateRangePicker(或类似命名的)用户控件,并添加RangeSlider和原始文本框。从文本框中删除重复的属性设置器,并将它们移动到Style

<UserControl x:Class="WpfTest2.DateRangePicker"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:WpfTest2">
  <StackPanel>
    <local:RangeSlider x:Name="rangeSlider" 
                        Minimum="1" Maximum="12" 
                        LowerValue="1" UpperValue="12" />

    <UniformGrid Columns="12" Rows="1" Margin="8,5,20,0">
      <UniformGrid.Resources>
        <Style TargetType="TextBox">
          <Setter Property="Margin" Value="2,0,0,0" />
          <Setter Property="FontFamily" Value="Tahoma" />
          <Setter Property="IsReadOnly" Value="True" />
          <Setter Property="Focusable" Value="False" />
          <Setter Property="TextAlignment" Value="Center" />
          <Setter Property="SelectionBrush" Value="{x:Null}" />
          <Setter Property="BorderBrush"
                      Value="{Binding RelativeSource={RelativeSource Self}, Path=Foreground}" />
          <Setter Property="Foreground">
            <Setter.Value>
              <MultiBinding Mode="OneWay">
                <MultiBinding.Converter>
                  <local:InRangeConverter />
                </MultiBinding.Converter>
                <Binding ElementName="rangeSlider" Path="LowerValue" />
                <Binding RelativeSource="{RelativeSource Self}" Path="Tag" />
                <Binding ElementName="rangeSlider" Path="UpperValue" />
              </MultiBinding>
            </Setter.Value>
          </Setter>
        </Style>
      </UniformGrid.Resources>
      <TextBox Tag="1"  Text="Jan" />
      <TextBox Tag="2"  Text="Feb" />
      <TextBox Tag="3"  Text="Mar" />
      <TextBox Tag="4"  Text="Apr" />
      <TextBox Tag="5"  Text="May" />
      <TextBox Tag="6"  Text="Jun" />
      <TextBox Tag="7"  Text="Jul" />
      <TextBox Tag="8"  Text="Aug" />
      <TextBox Tag="9"  Text="Sep" />
      <TextBox Tag="10" Text="Oct" />
      <TextBox Tag="11" Text="Nov" />
      <TextBox Tag="12" Text="Dec" />
    </UniformGrid>
  </StackPanel>
</UserControl>

(注意:如果您决定想要从范围滑块中拆分日期标签,只需将原始StackPanel替换为UniformGrid }从上面开始,并将绑定更新为ElementName="root"而不是ElementName="rangeSlider"

我使用MultiBinding来设置Foreground。它依赖于这个自定义转换器:

public class InRangeConverter : IMultiValueConverter
{
    private static readonly SolidColorBrush SelectedBrush = 
        new SolidColorBrush(Color.FromArgb(0xFF, 0xF7, 0x8A, 0x09));

    private static readonly SolidColorBrush UnselectedBrush =
        new SolidColorBrush(Color.FromArgb(0x3F, 0xF7, 0x8A, 0x09));

    private static readonly object[] ConvertBackResult =
        { DependencyProperty.UnsetValue };

    public object Convert(object[] values, Type type, object p, CultureInfo c)
    {
        if (values?.Length == 3)
        {
            var lower = values[0] as double?;
            var value = values[1] as double?;
            var upper = values[2] as double?;

            if (value == null)
            {
                var stringValue = values[1]?.ToString();

                if (stringValue != null && double.TryParse(stringValue, out var d))
                    value = d;
            }

            if (value >= lower && value <= upper)
                return SelectedBrush;

            return UnselectedBrush;
        }

        return Brushes.Gray;
    }

    public object[] ConvertBack(object value, Type[] types, object p, CultureInfo c)
    {
        return ConvertBackResult;
    }
}

您不清楚 是如何调整颜色的,所以我根据日期是否在所选范围内来更改颜色。您可以根据需要调整逻辑和颜色。

结果:

Date Range Picker Screenshot

注意:现在,您可以设置小于较低值的上限值。你应该解决这个问题。