C# 在绑定到DataTable时更改DataGrid上的空值外观

C# 在绑定到DataTable时更改DataGrid上的空值外观,c#,wpf,mvvm,datagrid,datatable,C#,Wpf,Mvvm,Datagrid,Datatable,我有DataGrid,它绑定到DataTable,因为我不知道编译时的列数 XAML <Window.Resources> <wpfApplication1:MainWindowViewModel x:Key="ViewModel" /> </Window.Resources> <Grid DataContext="{StaticResource ViewModel}"> <DataGrid x:Name="MyDataGr

我有
DataGrid
,它绑定到
DataTable
,因为我不知道编译时的列数

XAML

<Window.Resources>
    <wpfApplication1:MainWindowViewModel x:Key="ViewModel" />
</Window.Resources>

<Grid DataContext="{StaticResource ViewModel}">
    <DataGrid x:Name="MyDataGrid" 
              ItemsSource="{Binding Path=DataTable}" />
</Grid>
class MainWindowViewModel : INotifyPropertyChanged
{
    private DataTable dt;
    public event PropertyChangedEventHandler PropertyChanged;

    public MainWindowViewModel()
    {
        DataTable table = new DataTable();
        table.Columns.Add("Foo", typeof(int));
        table.Columns.Add("Bar", typeof(string));
        table.Rows.Add(1, "first");
        table.Rows.Add(2, null);
        DataTable = table;
    }

    private void OnPropertyChanged(string s)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(s));
        }
    }

    public DataTable DataTable
    {
        get { return dt; }
        set
        {
            dt = value;
            OnPropertyChanged("DataTable");
        }
    }
}
结果是:

单元格中没有值为
null
的内容。 我的问题是:如何在不更改源
数据表的情况下将
null
值的所有单元格更改为“-”

我无法在绑定中使用converter,因为它将尝试转换所有的
数据表
,而不是值。 我对
DataGridCell
样式也没有什么好运气,因为我不知道如何获取数据值并对其进行更改

编辑

<Window.Resources>
    <wpfApplication1:MainWindowViewModel x:Key="ViewModel" />
</Window.Resources>

<Grid DataContext="{StaticResource ViewModel}">
    <DataGrid x:Name="MyDataGrid" 
              ItemsSource="{Binding Path=DataTable}" />
</Grid>
class MainWindowViewModel : INotifyPropertyChanged
{
    private DataTable dt;
    public event PropertyChangedEventHandler PropertyChanged;

    public MainWindowViewModel()
    {
        DataTable table = new DataTable();
        table.Columns.Add("Foo", typeof(int));
        table.Columns.Add("Bar", typeof(string));
        table.Rows.Add(1, "first");
        table.Rows.Add(2, null);
        DataTable = table;
    }

    private void OnPropertyChanged(string s)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(s));
        }
    }

    public DataTable DataTable
    {
        get { return dt; }
        set
        {
            dt = value;
            OnPropertyChanged("DataTable");
        }
    }
}
我的最终解决方案基于其中一个答案。我创建
MyDataGrid
类并重写自动生成列的
方法

class MyDataGrid : DataGrid
{
    protected override void OnAutoGeneratingColumn(DataGridAutoGeneratingColumnEventArgs e)
    {
        var textColumn = e.Column as DataGridTextColumn;

        if (textColumn != null)
        {
            var binding = textColumn.Binding;
            binding.TargetNullValue = "-";
        }

        base.OnAutoGeneratingColumn(e);
    }
}

尝试更改datatable中的空值,如下所示:

if (dt != null)
{
    foreach (DataRow row in dt.Tables[0].Rows)
    {
        foreach (DataColumn col in dt.Tables[0].Columns)
        {
            string type = col.DataType.Name;

            if (row.IsNull(col))
            {
                if (type == "String") //for string values
                {
                    row.SetField(col, "-");
                }
                else // for integer
                {
                    row.SetField(col, 0);
                }
            }

        }
    }
}

您可以尝试使用此功能:

private string SomeString = null;

...

table.Rows.Add(2, ReturnNullValue(SomeString, "---"));

private string ReturnNullValue(string Value, string NullValue) 
{
    if (String.IsNullOrEmpty(Value) == true)
    {
        return NullValue;
    }

    return Value;
}
或者,您可以添加具有其他逻辑的属性:

private string _someString = "";

public string SomeString
{
    get
    {
        return _someString;
    }

    set
    {
        if (String.IsNullOrEmpty(value) == false)
        {
            _someString = value;
        }
        else
        {
            _someString = "---";
        }
    }
}
然后像这样使用:

SomeString = "";
table.Rows.Add(2, SomeString);

我认为我们可以不用编辑
DataTable
,这不是一个简单而快速的解决方案,因为这里的转换器、样式和功能都很弱。

也许您可以创建一个继承
DataTable
ViewModel
类,或者只保留该
DataTable
类的引用。该
ViewModel
类是您绑定到
DataGrid
的ItemSource的对象。然后,
ViewModel
应该知道它应该或不应该转换哪些数据(
null
s到“-”)并返回到
DataGrid
。这样,
DataTable
保持不变。

您可以订阅AutoGeneratingColumn事件,并用一个绑定替换绑定,该绑定将FallbackValue/TargetNullValue设置为您喜欢的值。我用过克隆技术


谢谢,这是一种方法,但如果可能的话,我试图在不更改数据表的情况下找到解决方案。您可以在网格单元值和替换中执行相同的操作。我希望留在MVVM模式中,而不是使用一些手动编辑。谢谢,这是一种方法,但是,如果可能的话,我试图找到一个不改变数据表的解决方案。我只是在猜测……我们可以继承数据表并使用这种新的数据表类型进行绑定吗?@theinsaneon我不知道它有什么帮助哦,sry……下面的答案是最好的方法……我对这个解决方案做得太过分了:P我的错……这是个好主意,谢谢。我创建了
MyDataTable:DataTable
并根据您的方法修改了自动生成列的方法。但是我有一个问题:为什么要克隆绑定对象?啊,对。在这种情况下,这是不必要的。如果绑定是通过BindingOperations.GetBinding()获得的,则在尝试更改绑定值时会引发异常。因为这里的绑定只是设置为CLR属性,所以不需要克隆它。