如何绑定多种颜色来填充WPF中的矩形?

时间:2014-11-02 22:01:39

标签: c# wpf xaml

我将ItemsControl绑定到名为SwatchThumbnails的可观察集合,该集合将包含数据以生成矩形。矩形可以有1-3种与之关联的颜色,并且在渲染时需要显示多种颜色。我想我理解如何只将一种颜色绑定到填充,但我需要一种方法来绑定三个并让它们均匀显示。怎么办呢?

这是我的XAML:

<ScrollViewer x:Name="sv_Thumbnails" Grid.ColumnSpan="2" Grid.Row="1" VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Auto">
    <ItemsControl x:Name="ug_Thumbnails" ItemsSource="{Binding SwatchThumbnails, ElementName=mainWindow}">
         <ItemsControl.ItemsPanel >
             <ItemsPanelTemplate>
                <UniformGrid Columns="6" RenderTransformOrigin="0,0.5" Cursor="Hand">
                  <Rectangle Width="50" Height="50" Fill="{Binding Color}" Margin="0 0 5 0" />
                </UniformGrid>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
    </ItemsControl>
</ScrollViewer>

我最初是通过C#代码将矩形形状插入UniformGrid,所以我有原始代码,用于分割颜色。基本上,这是我生成矩形的原始代码:

        System.Windows.Shapes.Rectangle swatch = new System.Windows.Shapes.Rectangle();
        swatch.Width = 50;
        swatch.Height = 50;
        swatch.Margin = new Thickness(0, 5, 5, 0);
        swatch.StrokeThickness = 1;
        swatch.Stroke = System.Windows.Media.Brushes.Gray;
        swatch.Name = "s_" + _name.ToString();
        double groupsize = 100 / _colors.Count();
        DrawingBrush blackBrush = new DrawingBrush();
        DrawingGroup checkersDrawingGroup = new DrawingGroup();
        List<SolidColorBrush> brushes = _colors;
        double location = 0;
        for (int i = 0; i < _colors.Count(); i++)
        {
            GeometryDrawing drawing = new GeometryDrawing(brushes[i], null,
                new RectangleGeometry(new Rect(0, location, groupsize, groupsize)));
            checkersDrawingGroup.Children.Add(drawing);
            location += groupsize;
        }
        blackBrush.Drawing = checkersDrawingGroup;
        swatch.Fill = blackBrush;
        swatch.MouseUp += new MouseButtonEventHandler(loadSwatchResources);

最后,这是我的可观察集合和样本缩略图定义。

    private ObservableCollection<SwatchThumbnail> swatchThumbnails = new ObservableCollection<SwatchThumbnail>();
    public ObservableCollection<SwatchThumbnail> SwatchThumbnails 
    {
        get { return swatchThumbnails; }
        set { swatchThumbnails = value; }
    }

public class SwatchThumbnail : INotifyPropertyChanged
{
    public string name { get; set; }
    public List<Color> colors { get; set; }
    public bool selected { get; set; }

    public event PropertyChangedEventHandler PropertyChanged;
}

2 个答案:

答案 0 :(得分:2)

您希望每个缩略图的背景实际上看起来像一个垂直LinearGradientBrush,因此这里的最佳选择是LinearGradientBrush,而不是DrawingBrush这对于这种情况来说过于复杂(并且过度杀伤) 。您需要一些Colors属性(实现了INotifyPropertyChanged),其中包含Colors范围。要将其转换为LinearGradientBrush,您需要Converter。据我所知,所有色带应具有相等的高度(和全宽)。幸运的是,LinearGradientBrush中的Offset与整个高度相对(以某种比例),因此我们不需要任何关于相关矩形的实际高度的信息。这是Converter类:

public class ColorsToLinearGradientBrushConverter : IValueConverter {
   public object Convert(object value, Type targetType, object parameter,
                                                        CultureInfo culture){
      var colors = (List<Color>) value;
      var brush = new LinearGradientBrush(){ StartPoint = new Point(),
                                             EndPoint = new Point(0,1)};
      var w = 1d / colors.Count;
      for(var i = 0; i < colors.Count - 1; i++){
         var offset = w * (i+1);
         var stop1 = new GradientStop(colors[i], offset);
         var stop2 = new GradientStop(colors[i+1], offset);
         brush.GradientStops.Add(stop1);
         brush.GradientStops.Add(stop2);
      }
      return brush;
   }
   //this way back is not needed (bind OneWay)
   public object ConvertBack(object value Type targetType, object parameter,
                                                           CultureInfo culture){
      throw new NotImplementedException();
   }
}

请注意,Colors属性的类型应为List<Color>(您的原始属性的类型为List<SolidColorBrush>)。

将您的Converter定义为XAML中的一些资源,并将其正常用于绑定(我希望您知道这一点)。这是XAML代码:

<ScrollViewer x:Name="sv_Thumbnails" Grid.ColumnSpan="2" Grid.Row="1"
    VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Auto">
   <ScrollViewer.Resources>
     <local:ColorsToLinearGradientBrushConverter x:Key="brushConverter"/>
   </ScrollViewer.Resources>
   <ItemsControl x:Name="ug_Thumbnails" ItemsSource="{Binding SwatchThumbnails, 
                                                      ElementName=mainWindow}">
     <!--ItemsControl.ItemsPanel>
         <ItemsPanelTemplate>
            <UniformGrid Columns="6" RenderTransformOrigin="0,0.5" Cursor="Hand">
            </UniformGrid>
        </ItemsPanelTemplate>
     </ItemsControl.ItemsPanel-->

     <ItemsControl.ItemTemplate>
        <DataTemplate>
          <Rectangle Width="50" Height="50" Fill="{Binding Colors,
                                     Converter={StaticResource brushConverter}}" 
                         Margin="0 0 5 0" />
        </DataTemplate>
     </ItemsControl.ItemTemplate>
   </ItemsControl>
</ScrollViewer>

请注意,您必须在此使用一些ItemTemplate,原始XAML只有ItemsPanel,它会更改项目的整个容器。如果这是您想要的,只需正常指定该面板,但请记住它只与 如何安排和布局 项目相关。这意味着我们不能仅仅根据它来为每个项目绑定背景。

更新 :我认为您已正确实施SwatchThumbnail。但看起来你没有。因此,请尝试以下实现,看看它是否有效:

public class SwatchThumbnail : INotifyPropertyChanged {
  public event PropertyChangedEventHandler PropertyChanged;
  protected void OnPropertyChanged(string prop){
    var handler = PropertyChanged;
    if(handler != null) handler(this, new PropertyChangedEventArgs(prop));
  }
  string _name;
  public string name {
    get { return _name;}
    set { 
       if(_name != value) {
          _name = value;
          OnPropertyChanged("name");
       }
    }
  }
  List<SolidColorBrush> _colors;
  public List<SolidColorBrush> colors {
    get {
       return _colors;
    }
    set {
       _colors = value;
       OnPropertyChanged("colors");
    }
  }
  bool _selected;
  public bool selected {
    get {
       return selected;
    }
    set {
       if(_selected != value){
          _selected = value;
          OnPropertyChanged("selected");
       }
    }
  }
}

答案 1 :(得分:0)

据我所知,最简单的方法是使用DrawingBrush代替SolidColorBrush

您的DrawingBrush将描述用于填充矩形的图案(在您的情况下,您将使用三个SolidColor画笔来绘制DrawingBrush的内容)。 然后,矩形的Fill属性应绑定到DrawingBrush。

请参阅有关如何将DrawingBrush用作矩形填充的说明here