简体   繁体   English

C#Wpf绘图与组合框

[英]C# Wpf drawing with Combobox

I need help with drawing in my combobox. 我需要在组合框中进行绘图的帮助。 I want to make a combobox of colors for picking. 我想选一个颜色组合框。 I found some stuff on the internet but none of them is working. 我在互联网上找到了一些东西,但是都没有用。 So far I have this : 到目前为止,我有这个:

 private void MyComb_DrawItem(object sender, DrawItemEventArgs e)
        {
            Graphics g = e.Graphics;
            System.Drawing.Rectangle rect = e.Bounds;
            ColorConverter converter = new ColorConverter();
             if (e.Index >= 0)
             {
             string n = ((ComboBox)sender).Items[e.Index].ToString();
              System.Drawing.Color c = (System.Drawing.Color)converter.ConvertFromString(n);
                SolidBrush b = new SolidBrush(c);
              g.FillRectangle(b, rect.X + 110, rect.Y + 5,
                  rect.Width - 10, rect.Height - 10);
          }

        }

This is my drawItem method 这是我的drawItem方法

<Grid>
        <ComboBox x:Name="MyComb" HorizontalAlignment="Left" Margin="66,81,0,0" VerticalAlignment="Top" Width="120" />

    </Grid>

This is definition of combobox 这是组合框的定义

Type colorType = typeof(System.Drawing.Color);
            PropertyInfo[] propInfoList = colorType.GetProperties(BindingFlags.Static |
                                                                  BindingFlags.DeclaredOnly | BindingFlags.Public);
            foreach (PropertyInfo c in propInfoList)
            {
                MyComb.Items.Add(c.Name);

            }

And here I am filling combobox with colors names and then I want to fill to combox with real colors according to the colors names.. But my draw item method is never called. 在这里,我用颜色名称填充组合框,然后根据颜色名称用实色填充combox。.但是我的绘制项目方法从未调用过。 I tried to create some DrawItem handler but, my combobox have no such thing... Then I read something about setting a DrawMode property of combobox, but my combobox doesn't that kind of property at all... I am using net framework v.4.6.1 Can please anyone tell me, what am I missing ? 我试图创建一些DrawItem处理程序,但是,我的组合框没有这样的东西。。。然后,我读了一些有关设置组合框的DrawMode属性的信息,但是我的组合框根本没有那种属性。 v.4.6.1谁能告诉我,我想念什么?

Thank you very much 非常感谢你

The biggest problem you're having is that you're trying to use code examples that were written for the Winforms API, even though you are using the WPF API. 您遇到的最大问题是,即使您使用的是WPF API,也要尝试使用为Winforms API编写的代码示例。 For future reference, you really need to be more careful about identifying the context of tutorials and other resources you find online, to make sure they actually apply to your scenario. 为了将来参考,您确实需要更加谨慎地标识在网上找到的教程和其他资源的上下文,以确保它们确实适用于您的方案。

As it happens, we have a number of related questions on Stack Overflow already: 碰巧的是,我们在堆栈溢出方面已经有许多相关问题:

WPF ComboBox as System.Windows.Media.Colors > WPF ComboBox作为System.Windows.Media.Colors >
WPF - Bind ComboBox Item Foreground to Its Value WPF-将ComboBox项绑定到其值的前景
Very simple color picker made of combobox 由组合框制成的非常简单的颜色选择器

These are all potentially useful to you, but are all based on the answer to this question: 这些都可能对您有用,但都是基于此问题的答案:

How can I list colors in WPF with XAML? 如何使用XAML在WPF中列出颜色?

Which was originally about just displaying the names of colors, and so took a short-cut, using the <ObjectDataProvider/> element in XAML. 最初只用于显示颜色名称 ,因此使用XAML中的<ObjectDataProvider/>元素进行了捷径。 This led to the need to use a converter in the other questions, to convert either from a string value or a PropertyInfo instance to the appropriate color or brush. 这导致需要在其他问题中使用转换器,以将string值或PropertyInfo实例转换为适当的颜色或画笔。

In fact, if your code is already written to use some type of MVVM approach, and especially since you've already written code-behind to retrieve the color values from the Colors type, or at least tried to (one of the problems in your code is that you are using the Winforms Color type instead of the WPF Colors type…again, in Winforms that works fine, but the WPF API follows the Code Analysis/FxCop rules more closely, and the named colors are in the Colors type), it makes sense to just stick with that and provide a direct view model data structure to which you can bind. 实际上,如果您的代码已经被编写为使用某种类型的MVVM方法,尤其是因为您已经编写了代码以从Colors类型中检索颜色值,或者至少尝试这样做(您的问题之一,代码是您使用的是Winforms Color类型而不是WPF Colors类型……同样,在Winforms中可以正常工作,但是WPF API更严格地遵循Code Analysis / FxCop规则,并且命名的颜色为Colors类型),坚持这样做并提供可以绑定的直接视图模型数据结构是很有意义的。

In this approach, rather than providing a procedural implementation of the item drawing, you provide in XAML a declarative implementation describing what each item should look like. 在这种方法中,您没有在XAML中提供声明性的实现,而是描述了每个项目的外观,而不是提供项目图的过程实现。

Here is an example… 这是一个例子……

First, some simple view model data structures: 首先,一些简单的视图模型数据结构:

// Very simple container class
class ColorViewModel
{
    public Brush Brush { get; }
    public string Name { get; }

    public ColorViewModel(Brush brush, string name)
    {
        Brush = brush;
        Name = name;
    }
}

// Main view model, acts as the data context for the window
class MainViewModel : INotifyPropertyChanged
{
    public IReadOnlyList<ColorViewModel> Colors { get; }

    private Brush _selectedColor;
    public Brush SelectedColor
    {
        get { return _selectedColor; }
        set { _UpdateField(ref _selectedColor, value); }
    }

    public MainViewModel()
    {
        Colors = typeof(Colors).GetProperties(BindingFlags.Static | BindingFlags.Public)
            .Select(p => new ColorViewModel(new SolidColorBrush((Color)p.GetValue(null)), p.Name))
            .ToList().AsReadOnly();
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void _UpdateField<T>(ref T field, T newValue, [CallerMemberName] string propertyName = null)
    {
        if (!EqualityComparer<T>.Default.Equals(field, newValue))
        {
            field = newValue;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

With those in hand, the XAML is straight-forward: 有了这些,XAML就很简单了:

<Window x:Class="TestSO47850587ColorComboBox.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:l="clr-namespace:TestSO47850587ColorComboBox"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">

  <Window.DataContext>
    <l:MainViewModel/>
  </Window.DataContext>

  <StackPanel>
    <ComboBox Width="100" ItemsSource="{Binding Colors}"
              HorizontalAlignment="Left" Grid.IsSharedSizeScope="True"
              SelectedValuePath="Brush" SelectedValue="{Binding SelectedColor}">
      <ComboBox.ItemTemplate>
        <DataTemplate DataType="{x:Type l:ColorViewModel}">
          <Grid>
            <Grid.ColumnDefinitions>
              <ColumnDefinition Width="Auto" SharedSizeGroup="ComboBoxItem"/>
            </Grid.ColumnDefinitions>
            <TextBlock Text="{Binding Name}" Background="{Binding Brush}" HorizontalAlignment="Stretch"/>
          </Grid>
        </DataTemplate>
      </ComboBox.ItemTemplate>
    </ComboBox>

    <Rectangle HorizontalAlignment="Stretch" Height="24" Fill="{Binding SelectedColor}"/>
  </StackPanel>
</Window>

The above displays the color names, using the actual color as the background. 上面以实际颜色为背景显示颜色名称。 If all you really want is a rectangle, then you can replace the <TextBlock/> element with a <Rectangle/> element, binding to its Fill property. 如果您只想要一个矩形,则可以将<TextBlock/>元素替换为<Rectangle/>元素,并绑定到其Fill属性。 Naturally, you can achieve other visual effects, such as a rectangle with a margin. 当然,您可以实现其他视觉效果,例如带有边距的矩形。 It's just a matter of configuring your data template according to your need. 只需根据需要配置数据模板即可。

The main point here is that you should embrace the data binding approach that defines good WPF programming, and that you should definitely not mistake Winforms code examples for WPF. 这里的要点是,您应该采用定义良好WPF编程的数据绑定方法,并且绝对应该将Winforms代码示例误认为WPF。 :) :)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM