【问题标题】:Combobox binding in Datatemplate数据模板中的组合框绑定
【发布时间】:2011-08-15 14:45:21
【问题描述】:

您好,我实际上是在创建 WPF DataGrid 自定义控件。 想要这个组合应该在组合框中显示性别以及当我将组合框保持在数据模板之外它的工作但在数据模板内部它不工作时发生了什么。请帮帮我?

<UserControl x:Class="Custom_DataGrid.Grid3.Grid3"
             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" 
             mc:Ignorable="d" xmlns:sdk="http://schemas.microsoft.com/wpf/2008/toolkit"
             d:DesignHeight="300" d:DesignWidth="300" >
    <UserControl.Resources>

        <DataTemplate x:Key="dueDateCellTemplate">
            <TextBlock Text="{Binding DOB}" Margin="5,4,5,4"/>
        </DataTemplate>
        <DataTemplate x:Key="dueDateCellEditingTemplate">
            <DatePicker SelectedDate="{Binding DOB, Mode=TwoWay}"/>
        </DataTemplate>

        <DataTemplate x:Key="genderCellTemplate">
            <TextBlock Text="{Binding GENDER.Gender}" Margin="5,4,5,4"/>
        </DataTemplate>
        <DataTemplate x:Key="genderCellEditingTemplate">
            <!--<ComboBox ItemsSource="{Binding Genders}" SelectedItem="{Binding Genders}" SelectedValue="{Binding Path=GENDER, ElementName=Id}" DisplayMemberPath="Id" SelectedValuePath="Gender"></ComboBox>-->
            <ComboBox x:Name="c1" ItemsSource="{Binding Genders}" DisplayMemberPath="Id"  Height="50" Width="100"></ComboBox>
            <!--<TextBlock Text="{Binding Genders.Gender}" Foreground="Khaki"></TextBlock>-->
        </DataTemplate>

    </UserControl.Resources>
    <Grid>
        <DataGrid x:Name="datagrid3" AutoGeneratingColumn="datagrid3_AutoGeneratingColumn" ItemsSource="{Binding Employees}" Foreground="SteelBlue"></DataGrid>

    </Grid>
</UserControl>
public enum Designation
    {
        Sales, Development, HR, BackOffice
    }

public class Sex
    {
        private string id;
        private string gen;

        public string Id
        {
            get
            {
                return id;
            }
            set
            {
                id = value;
            }
        }

        public string Gender
        {
            get
            {
                return gen;
            }
            set
            {
                gen = value;
            }
        }

    }

public class DataSource
    {
        ObservableCollection<Employee> empList = new ObservableCollection<Employee>();
        List<Sex> genders = new List<Sex>();



        public DataSource()
        {

            empList.Add(new Employee() { ID = 1, NAME = "Neeraj", DOB = Convert.ToDateTime("12/03/1986"), EMAIL = "neeraj@mail.com", GENDER = new Sex() { Id = "M", Gender = "Male" }, PHONE = "9999999999", ACTIVE = false, DESIGNATION = Designation.Development });
            empList.Add(new Employee() { ID = 2, NAME = "Mayank", DOB = Convert.ToDateTime("01/01/1986"), EMAIL = "mayank@mail.com", GENDER = new Sex() { Id = "M", Gender = "Male" }, PHONE = "9999999999", ACTIVE = true, DESIGNATION = Designation.BackOffice });
            empList.Add(new Employee() { ID = 1, NAME = "Neeraj", DOB = Convert.ToDateTime("12/03/1986"), EMAIL = "neeraj@mail.com", GENDER = new Sex() { Id = "M", Gender = "Male" }, PHONE = "9999999999", ACTIVE = false, DESIGNATION = Designation.Development });
            empList.Add(new Employee() { ID = 2, NAME = "Mayank", DOB = Convert.ToDateTime("01/01/1986"), EMAIL = "mayank@mail.com", GENDER = new Sex() { Id = "M", Gender = "Male" }, PHONE = "9999999999", ACTIVE = true, DESIGNATION = Designation.BackOffice });
            empList.Add(new Employee() { ID = 1, NAME = "Neeraj", DOB = Convert.ToDateTime("12/03/1986"), EMAIL = "neeraj@mail.com", GENDER = new Sex() { Id = "M", Gender = "Male" }, PHONE = "9999999999", ACTIVE = false, DESIGNATION = Designation.Development });
            empList.Add(new Employee() { ID = 2, NAME = "Mayank", DOB = Convert.ToDateTime("01/01/1986"), EMAIL = "mayank@mail.com", GENDER = new Sex() { Id = "M", Gender = "Male" }, PHONE = "9999999999", ACTIVE = true, DESIGNATION = Designation.BackOffice });

            genders.Add(new Sex() { Id = "M", Gender = "Male" });
            genders.Add(new Sex() { Id = "F", Gender = "Female" });


        }




        public ObservableCollection<Employee> Employees
        {
            get
            {
                return empList;
            }
            set
            {
                empList = value;
            }
        }

        public List<Sex> Genders
        {
            get
            {
                return genders;
            }
            set
            {
                genders = value;
            }
        }


    }

xaml.cs 文件的编码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
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 Custom_DataGrid.Grid3
{
    /// <summary>
    /// Interaction logic for Grid3.xaml
    /// </summary>
    public partial class Grid3 : UserControl
    {
        public Grid3()
        {
            InitializeComponent();
            this.DataContext = new DataSource();
        }

        private void datagrid3_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
        {
            if (e.PropertyName.ToLower().ToString().Equals("id"))
            {
                e.Column.Header = "Employee Id";
            }
            else if (e.PropertyName.ToLower().Equals("name"))
            {
                e.Column.Header = "Employee Name";
            }
            else if (e.PropertyName.ToLower().Equals("dob"))
            {
                e.Column.Header = "Employee DOB";
                if (e.PropertyType == typeof(DateTime))
                {
                    DataGridTemplateColumn templateColumn = new DataGridTemplateColumn();
                    templateColumn.Header = "Employee DOB";
                    templateColumn.CellTemplate = (DataTemplate)Resources["dueDateCellTemplate"];
                    templateColumn.CellEditingTemplate = (DataTemplate)Resources["dueDateCellEditingTemplate"];
                    templateColumn.SortMemberPath = "DueDate";
                    e.Column = templateColumn;
                }
            }
            else if (e.PropertyName.ToLower().Equals("phone"))
            {
                e.Column.Header = "Employee Phone";
                e.Cancel = true;
            }
            else if (e.PropertyName.ToLower().Equals("email"))
            {
                e.Column.Header = "Employee Email";
            }
            else if (e.PropertyName.ToLower().Equals("gender"))
            {
                e.Column.Header = "Employee Gender";
                DataGridTemplateColumn templateColumn = new DataGridTemplateColumn();
                templateColumn.Header = "Employee Gender";
                templateColumn.CellTemplate = (DataTemplate)Resources["genderCellTemplate"];
                templateColumn.CellEditingTemplate = (DataTemplate)Resources["genderCellEditingTemplate"];
                e.Column = templateColumn;
            }
            else if (e.PropertyName.ToLower().Equals("active"))
            {
                e.Column.Header = "Employee Active/InActive";
            }
            else if (e.PropertyName.ToLower().Equals("designation"))
            {
                e.Column.Header = "Employee Designation";
            }
        }



    }
}

所以我正在尝试使用 celleditingtemplate 中的 combobxo 创建模板列,一切正常,但在 datatemplate 内部却无法正常工作。 请帮我?检查我评论过的文本框工作正常...

【问题讨论】:

    标签: wpf datagrid


    【解决方案1】:

    如果您在 DataTemplate 中,则 DataContext 将是被模板化的对象。因此,如果仅指定了绑定路径,则相对于 DataContext 的绑定将找不到 ItemsSource。

    通常您可以使用RelativeSource-binding 来查找仍然具有可以在其中找到您的 ItemsSource 的 DataContext 的控件。 (请参阅 RV1987 的回答;我认为它早先不起作用,因为如果您有一个 DataGridComboBoxColumn,那么相同的 RelativeSource-ItemsSource-binding 将不起作用,那是因为它自己的列是抽象的,不像模板创建的控件那样出现在树中)

    由于 UserControl 的 DataContext 应该是您要查找的内容,因此您可以命名您的 UserControl(例如control)并像这样绑定:

    ItemsSource="{Binding Source={x:Reference control}, Path=DataContext.Genders}"
    

    (请注意,x:Reference 是相当新的,它在 .NET 3.5 中不存在,使用 ElementName=control 代替将不工作)

    【讨论】:

      【解决方案2】:

      尝试在您的数据模板中使用它 -

      <ComboBox x:Name="c1" ItemsSource="{Binding DataContext.Genders, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" DisplayMemberPath="Id"  Height="50" Width="100"></ComboBox>
      

      这将在您的用户控件的数据上下文中找到属性 Genders,即 DataSource。

      【讨论】:

      • 我怀疑这是否可行,因为 DataTemplate 应用于 DataGrid 单元格。此外,Genders 不是 UserControl 本身的属性。编辑:从头开始,如果你转到根目录,这实际上可能有效,但路径可能应该是DataContext.Genders。
      • 是的,不错的收获……我差点错过了……!!我没有使用过'x:Reference',所以不确定它是如何工作的..
      • 其实我很惊讶这个工作,如果你试图找到 DataGrid 并绑定到它的 DataContext(应该相同)不起作用。
      • 也许由于资源位于 UserControl 中,它能够向上追溯至其层次结构,直至 usercontrol,但不能追溯至 datagrid。可能是,但我不确定。
      • 我找到了原因,很久以前我在代码隐藏中搞砸了我的 DataGrid.DataContext,facepalms...
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-19
      相关资源
      最近更新 更多