WPF DataGrid在同一列中的不同控件 - 不正确的绑定

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WPF DataGrid在同一列中的不同控件 - 不正确的绑定相关的知识,希望对你有一定的参考价值。

我正在开发应用程序,它对项目列表执行检查。每个项目都有需要对其执行的检查列表。每个检查可以是3种类型之一:CheckBox,ComboBox,TextBox。

我想让Datagrid有2列(一个用于项目名称,第二列用于检查列表)。第二列包含另一个具有2列的DataGrid(一列用于检查名称,第二列用于检查控制)。目的是在与Check模型绑定的同一列中使用不同类型的控件。

问题是与CheckValue的绑定不起作用,但与所有其他属性的绑定工作正常。

最后一列包含CheckBoxes,TextBox和ComboBox,但它们没有填充任何值。有谁知道下面的代码有什么问题?

以下是模型类的示例

public class Item
{
    public string ItemName { get; set; }
    public ObservableCollection<Check> Checks { get; set; }

    public Item()
    {
        Checks = new ObservableCollection<Check>();
    }
}

public enum CheckType
{
    CheckBox,
    ComboBox,
    TextBox
}

public abstract class Check
{        
    public string CheckName { get; set; }
    public CheckType CheckType { get; protected set; }
    public abstract object CheckValue { get; set; }
}

public class CheckBox : Check
{
    private bool checkValue;

    public CheckBox()
    {
        CheckType = CheckType.CheckBox;
    }

    public override object CheckValue
    {
        get
        {
            return checkValue;
        }
        set
        {
            checkValue = (bool)value;
        }
    }
}

public class ComboBox : Check
{
    private List<string> checkValue;

    public ComboBox()
    {
        CheckType = CheckType.ComboBox;
    }

    public override object CheckValue
    {
        get
        {
            return checkValue;
        }
        set
        {
            checkValue = value as List<string>;
        }
    }
}

public class TextBox : Check
{
    private string checkValue;

    public TextBox()
    {
        CheckType = CheckType.TextBox;
    }

    public override object CheckValue
    {
        get
        {
            return checkValue;
        }
        set
        {
            checkValue = value as string;
        }
    }
}

public class MainViewModel
{
    public ObservableCollection<Item> Items { get; set; }

    public MainViewModel()
    {
        Items = new ObservableCollection<Item>();

        Item item = new Item();
        item.ItemName = "First item";

        Check check1 = new CheckBox() { CheckName = "Check 1", CheckValue = true };
        Check check2 = new CheckBox() { CheckName = "Check 2", CheckValue = false };
        Check text1 = new TextBox() { CheckName = "Check 3", CheckValue = "Please enter check" };
        Check combo1 = new ComboBox() { CheckName = "Check 4", CheckValue = new List<string> { "Value1", "Value2" } };

        item.Checks.Add(check1);
        item.Checks.Add(check2);
        item.Checks.Add(text1);
        item.Checks.Add(combo1);

        Items.Add(item);
    }
}

最后这里是主窗口的XAML代码。

<Window x:Class="ItemTest.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:vm ="clr-namespace:ItemTest"
    Title="MainWindow" Height="350" Width="525">
<Window.Resources>
    <vm:MainViewModel x:Key="mainViewModel"/>         
</Window.Resources>

<Grid DataContext="{Binding Source={StaticResource mainViewModel}}">
    <DataGrid ItemsSource="{Binding Path=Items}" AutoGenerateColumns="False">
        <DataGrid.Columns>
            <DataGridTextColumn Header="Item" Binding="{Binding ItemName}" /> 
            <DataGridTemplateColumn Header="Checks">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <DataGrid ItemsSource="{Binding Checks}" AutoGenerateColumns="False" HeadersVisibility="None">
                            <DataGrid.Columns>
                                <DataGridTextColumn Binding="{Binding CheckName}" />
                                <DataGridTemplateColumn>
                                    <DataGridTemplateColumn.CellTemplate>
                                        <DataTemplate>
                                            <ContentControl>
                                                <ContentControl.Style>
                                                    <Style TargetType="ContentControl">
                                                        <Style.Triggers>
                                                            <DataTrigger Binding="{Binding CheckType}" Value="CheckBox">
                                                                <Setter Property="ContentTemplate">
                                                                    <Setter.Value>
                                                                        <DataTemplate>
                                                                            <CheckBox IsChecked="{Binding CheckValue}"/>
                                                                        </DataTemplate>
                                                                    </Setter.Value>
                                                                </Setter>
                                                            </DataTrigger>
                                                            <DataTrigger Binding="{Binding CheckType}" Value="ComboBox">
                                                                <Setter Property="ContentTemplate">
                                                                    <Setter.Value>
                                                                        <DataTemplate>
                                                                            <ComboBox ItemsSource="{Binding CheckValue}" />
                                                                        </DataTemplate>
                                                                    </Setter.Value>
                                                                </Setter>
                                                            </DataTrigger>
                                                            <DataTrigger Binding="{Binding CheckType}" Value="TextBox">
                                                                <Setter Property="ContentTemplate">
                                                                    <Setter.Value>
                                                                        <DataTemplate>
                                                                            <TextBox Text="{Binding CheckValue}" />
                                                                        </DataTemplate>
                                                                    </Setter.Value>
                                                                </Setter>
                                                            </DataTrigger>
                                                        </Style.Triggers>
                                                    </Style>
                                                </ContentControl.Style>
                                            </ContentControl>
                                        </DataTemplate>
                                    </DataGridTemplateColumn.CellTemplate>
                                </DataGridTemplateColumn>
                            </DataGrid.Columns>
                        </DataGrid>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
    </DataGrid>
</Grid>

答案

只需设置ItemControl的Content属性:

<ContentControl Content="{Binding}">

WPF将自动将DataTemplate的DataContext设置为其父ContentControl的内容。但是在您的XAML中,您没有设置Content属性(您只指定ContentControl的Style,但忘记设置其内容)。

并且不要忘记在控件绑定上设置UpdateSourceTrigger=PropertyChanged,否则您可能在viewmodel中看不到更新。

另一答案

XAML示例工作,绑定BindingList:

<DataGrid x:Name="dataGridParametros"
        Grid.Row="1"
        Margin="5"
        AutoGenerateColumns="False"
        HeadersVisibility="All"
        ItemsSource="{Binding}"
        RowHeaderWidth="20"
        SelectionUnit="FullRow"
        ScrollViewer.CanContentScroll="True" 
        CanUserAddRows="false"
        ScrollViewer.VerticalScrollBarVisibility="Auto"
        ScrollViewer.HorizontalScrollBarVisibility="Auto" 
        FontFamily="Arial" 
        CellEditEnding="dataGridParametros_CellEditEnding" >
<DataGrid.Columns>
    <DataGridTextColumn Binding="{Binding IdParametro}" Header="Id" FontFamily="Arial" IsReadOnly="True" Visibility="Hidden"/>
    <DataGridTextColumn Binding="{Binding Codigo}" Header="Código" FontFamily="Arial" IsReadOnly="True"/>
    <DataGridTextColumn Width="200" Binding="{Binding Mnemonico}" Header="Mnemonico" FontFamily="Arial" IsReadOnly="True" />
    <DataGridTextColumn Width="250*" Binding="{Binding Descricao}" Header="Descrição" FontFamily="Arial" IsReadOnly="True" />
    <DataGridTemplateColumn Header="Valor" Width="150">
        <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
                <ContentControl Content="{Binding}">
                    <ContentControl.Style>
                        <Style TargetType="ContentControl">
                            <Style.Triggers>
                                <DataTrigger Binding="{Binding TipoCampo}" Value="CheckBox">
                                    <Setter Property="ContentTemplate">
                                        <Setter.Value>
                                            <DataTemplate>
                                                <CheckBox IsChecked="{Binding Valor , Mode=TwoWay , UpdateSourceTrigger=PropertyChanged}"/>
                                            </DataTemplate>
                                        </Setter.Value>
                                    </Setter>
                                </DataTrigger>
                                <DataTrigger Binding="{Binding TipoCampo}" Value="ComboBox">
                                    <Setter Property="ContentTemplate">
                                        <Setter.Value>
                                            <DataTemplate>
                                                <ComboBox ItemsSource="{Binding Valor , Mode=TwoWay , UpdateSourceTrigger=PropertyChanged}" />
                                            </DataTemplate>
                                        </Setter.Value>
                                    </Setter>
                                </DataTrigger>
                                <DataTrigger Binding="{Binding TipoCampo}" Value="TextBox">
                                    <Setter Property="ContentTemplate">
                                        <Setter.Value>
                                            <DataTemplate>
                                                <TextBox Text="{Binding Valor , Mode=TwoWay , UpdateSourceTrigger=PropertyChanged}" />
                                            </DataTemplate>
                                        </Setter.Value>
                                    </Setter>
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </ContentControl.Style>
                </ContentControl>
            </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>
    </DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>

以上是关于WPF DataGrid在同一列中的不同控件 - 不正确的绑定的主要内容,如果未能解决你的问题,请参考以下文章

WPF 在datagrid模板列中添加用户控件,在后台如何快速的检索到该控件。急!!!

WPF 格式化输出- IValueConverter接口的使用 datagrid列中的值转换显示

在 WPF 中的 DataGrid 列中获取 button_click 事件的行

WPF中ListView和DataGrid的区别?

去除WPF的DataGrid控件中的多余行

在编辑时修改 WPF DataGrid 中的用户控件