WPF:在 ComboBox 中使用 ItemsControl DataTemplate

WPF: Using the ItemsControl DataTemplate in ComboBox

我正在学习 WPF,并且正在尝试做一些简单的事情。我有两个 类:CandyMyColor。这两个类的代码是这样的

public class Candy
{
    public MyColor Color { get; set; }
    public string Name { get; set; }
}

public class MyColor
{
    public string Name { get; set; }
    public uint Id { get; set; }
}

(为了看得更清楚,我在下面附上了一张图片)

我在 window 中有一个区域,我可以在其中创建一个 MyColor,方法是使用插入 MyColor.Name 的文本框,以及一个递增 [=17] 的简单逻辑=].在 window 的另一边,我有一个按钮可以在包含 Candy 的 ItemsControl 中创建新项目。在这个 ItemsControl 中有一个 ComboBox 我可以指定 Candy.Color 和一个 TextBox 我可以指定 Candy.Name。最后,当我点击按钮 Generate List 时,代码应该以

格式输出在列表下方的 TextBox

Candy.Color Candy.Name

我正在尝试弄清楚如何自动填充 ComboBox 填充我创建的颜色列表,以便我可以指定 Candy 颜色,但我不知道如何绑定我的数据源。另外,我将如何生成文本?

目前我的代码是这样的

namespace QuestionToAsk
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    ObservableCollection<MyColor> Colors;
    ObservableCollection<Candy> Candies;

    public MainWindow()
    {
        InitializeComponent();
        Colors = new ObservableCollection<MyColor>();
        Candies = new ObservableCollection<Candy>();

        Colors.Add(new MyColor() { Name = "(Unspecified)", Id = 0 });

        icColors.ItemsSource = Colors;
        icCandies.ItemsSource = Candies;
    }

    private void btnColor(object sender, RoutedEventArgs e)
    {
        if (txtColor.Text != "")
        {
            uint last_id = Colors.Last<MyColor>().Id;
            Colors.Add(new MyColor() { Name = txtColor.Text, Id = last_id+1 });
            txtColor.Text = "";
        }
    }

    private void btnNewCandy(object sender, RoutedEventArgs e)
    {
        Candies.Add(new Candy());
    }

    private void btnGetList(object sender, RoutedEventArgs e)
    {
        //How to create the list of <Color, Name>?
    }
}

public class Candy
{
    public MyColor Color { get; set; }
    public string Name { get; set; }
}

public class MyColor
{
    public string Name { get; set; }
    public uint Id { get; set; }
}
}

我的 XML 文件如下所示:

<Window x:Class="QuestionToAsk.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:QuestionToAsk"
        Title="Color Candy Maker" Height="350" Width="525">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <DockPanel Margin="3">
            <Button Content="Add Color" Click="btnColor" DockPanel.Dock="Bottom"/>
            <TextBox x:Name="txtColor" DockPanel.Dock="Bottom"/>
            <ItemsControl x:Name="icColors" Grid.Column="0" Grid.Row="0" DockPanel.Dock="Top">
                <ItemsControl.ItemTemplate>
                    <DataTemplate x:Name="tColorsTemplate">
                        <TextBlock Text="{Binding Name}" Name="Color" />
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </DockPanel>
        <DockPanel Grid.Column="1" Grid.Row="0" Margin="3">
            <Grid DockPanel.Dock="Bottom">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
                <Button Content="New Candy" Click="btnNewCandy" Grid.Column="0"/>
                <Button Content="Generate List" Click="btnGetList" Grid.Column="1"/>
            </Grid>
            <ItemsControl Name="icCandies" DockPanel.Dock="Top">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="*" />
                                <ColumnDefinition Width="*" />
                            </Grid.ColumnDefinitions>
                            <ComboBox Name="cmbColors" Grid.Column="0">
                               <!-- How to bind this cmbColors to icColors? -->
                            </ComboBox>
                            <TextBox Text="{Binding Name}" Grid.Column="1" />
                        </Grid>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </DockPanel>
        <DockPanel  Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2">
            <TextBox x:Name="txtColorCandy"/>
        </DockPanel>
    </Grid>
</Window>

编辑

我已经删除了我所有的想法并使用你的硬设计实现了它:D.

xaml代码

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="*" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <DockPanel Margin="3">
        <Button Content="Add Color" Click="btnColor" DockPanel.Dock="Bottom"/>
        <TextBox x:Name="txtColor" DockPanel.Dock="Bottom"/>
        <ItemsControl x:Name="icColors" Grid.Column="0" Grid.Row="0" DockPanel.Dock="Top">
            <ItemsControl.ItemTemplate>
                <DataTemplate x:Name="tColorsTemplate">
                    <TextBlock Text="{Binding Name}" Name="Color" />
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </DockPanel>
    <DockPanel Grid.Column="1" Grid.Row="0" Margin="3">
        <Grid DockPanel.Dock="Bottom">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="*" />
            </Grid.ColumnDefinitions>
            <Button Content="New Candy" Click="btnNewCandy" Grid.Column="0"/>
            <Button Content="Generate List" Click="btnGetList" Grid.Column="1"/>
        </Grid>
        <ItemsControl Name="icCandies" DockPanel.Dock="Top">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="*" />
                        </Grid.ColumnDefinitions>
                        <ComboBox Name="cmbColors" Grid.Column="0"
                                  ItemsSource="{Binding Colors, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"
                                  DisplayMemberPath="Name"
                                  SelectedItem="{Binding Color}">
                        </ComboBox>
                        <TextBox Text="{Binding Name}" Grid.Column="1" />
                    </Grid>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </DockPanel>
    <DockPanel  Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2">
        <TextBox x:Name="txtColorCandy" VerticalScrollBarVisibility="Auto"/>
    </DockPanel>
</Grid>

注意 RelativeSource 的用法,因为 ComboBox 的值在 Window class 的 属性 中,而所选值是保存在Candyclass。所以 ItemsSource 绑定到 Window class 的 属性 并且 SelectedItem 绑定到 Candy 的 属性 class

代码隐藏

public partial class MainWindow : Window
{
    private ObservableCollection<MyColor> _colors;

    public IEnumerable<MyColor> Colors
    {
        get { return _colors; }
    }

    private ObservableCollection<Candy> _candies;

    public IEnumerable<Candy> Candies
    {
        get { return _candies; }
    }

    public MainWindow()
    {
        InitializeComponent();
        _colors = new ObservableCollection<MyColor>();
        _candies = new ObservableCollection<Candy>();

        _colors.Add(new MyColor { Name = "(Unspecified)", Id = 0 });
        icColors.ItemsSource = Colors;
        icCandies.ItemsSource = Candies;
    }

    private void btnColor(object sender, RoutedEventArgs e)
    {
        if (txtColor.Text != "")
        {
            uint last_id = Colors.Last<MyColor>().Id;
            _colors.Add(new MyColor() { Name = txtColor.Text, Id = last_id + 1 });
            txtColor.Text = "";
        }
    }

    private void btnNewCandy(object sender, RoutedEventArgs e)
    {
        _candies.Add(new Candy());
    }

    private void btnGetList(object sender, RoutedEventArgs e)
    {
        StringBuilder sb = new StringBuilder();
        foreach (var item in _candies)
        {
            if (item.Name == null || item.Color == null)
                continue;
            sb.AppendLine(item.Color.Name + " " + item.Name);
        }

        txtColorCandy.Text = sb.ToString();
    }
}

如果有任何困惑,请告诉我,我会尽力提供帮助