Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/269.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WPF中数据网格中的条件CanUserAddRows_C#_Wpf_Xaml_Datagrid - Fatal编程技术网

C# WPF中数据网格中的条件CanUserAddRows

C# WPF中数据网格中的条件CanUserAddRows,c#,wpf,xaml,datagrid,C#,Wpf,Xaml,Datagrid,假设我有一个组合框,如: <ComboBox SelectedValue="{Binding DataContext.CanUserAddMultipleRows, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Page}}, Converter={Static

假设我有一个组合框,如:

<ComboBox SelectedValue="{Binding DataContext.CanUserAddMultipleRows, 
                                  RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Page}},
                                 Converter={StaticResource yesNoToBooleanConverter}}">
    <ComboBoxItem>Yes</ComboBoxItem>
    <ComboBoxItem>No</ComboBoxItem>
</ComboBox>
现在我有了一个数据网格:

<DataGrid Grid.Row="7" Grid.Column="1" Grid.ColumnSpan="2" AutoGenerateColumns="False" 
          CanUserAddRows="{Binding DataContext.CanUserAddMultipleRows, 
                                   RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Page}}}"
          ItemsSource="{Binding DataContext.MyObject,
                                RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Page}}}">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Quantity" Binding="{Binding Quantity}"></DataGridTextColumn>
        <DataGridTextColumn Header="Rate" Binding="{Binding Rate}"></DataGridTextColumn>
        <DataGridTextColumn Header="Amount" Binding="{Binding Amount}"></DataGridTextColumn>
    </DataGrid.Columns>
</DataGrid>

现在,我希望在默认情况下为用户提供1行,这样,如果CanUserAddRows=false,那么他们也应该能够向DataGrid添加1项。若CanUserAddRows=true,那个么用户可以拥有他想要的任意数量的行


这件事可能很简单,但我对DataGrid还不熟悉。所以,我问了这个问题。

在我的示例中,有一个bool类型的
MayUserAddRows
属性。如果
MayUserAddRows==true
则用户可以添加尽可能多的记录,但如果
MayUserAddRows==false
则他只能填充一条记录

还具有
CanUserAddRows
属性,该属性直接与
DataGrid.CanUserAddRows
的属性绑定

ViewModel中的属性通过NotificationObject实现接口。他有一个事件
propertychangedventhandler(propertyName)
,通知通知属性。关键逻辑如下:

private void MyViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    if (e.PropertyName.Equals("MayUserAddRows")) 
    {
        // The MayUserAddRows property is changed
        if (MyViewModel.MayUserAddRows == true) 
        {
            // Allow to add a lot of records
            MyViewModel.CanUserAddRows = true;
        }

        if (MyViewModel.MayUserAddRows == false)
        {
            // Prohibit the addition 
            MyViewModel.CanUserAddRows = false;

            // And add the empty row
            AddEmptyRow(MyViewModel.MyCollection);
        }                
    }
}
下面是一个完整的示例:

XAML

<Window x:Class="ConditionalCanUserAddRows.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:this="clr-namespace:ConditionalCanUserAddRows"
        WindowStartupLocation="CenterScreen"
        Title="MainWindow" Height="300" Width="325">

    <Grid>
        <CheckBox Content="{Binding Path=IsChecked,
                                    RelativeSource={RelativeSource Mode=Self}}"
                  ContentStringFormat="May user add rows - {0}"
                  HorizontalAlignment="Left"
                  VerticalAlignment="Top"
                  IsChecked="{Binding Path=MayUserAddRows}" />

        <Button Content="Clear" 
                VerticalAlignment="Top"
                HorizontalAlignment="Right"
                Click="Clear_Click" />

        <DataGrid Name="SimpleDataGrid"
                  Width="200"
                  Height="200"
                  CanUserResizeColumns="False"                  
                  AutoGenerateColumns="False" 
                  RowHeaderWidth="0" 
                  CanUserAddRows="{Binding Path=CanUserAddRows, Mode=TwoWay}"
                  ItemsSource="{Binding Path=MyCollection}">

            <DataGrid.Columns>
                <DataGridTextColumn Width="1.5*"
                                    Header="Name"
                                    Binding="{Binding Path=Name}" />

                <DataGridTextColumn Header="Age"                                    
                                    Width="1.5*" 
                                    FontSize="14" 
                                    Binding="{Binding Path=Age}" />
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>
public partial class MainWindow : Window
{   
    ViewModel MyViewModel = new ViewModel();

    public MainWindow()
    {
        InitializeComponent();

        this.DataContext = MyViewModel;

        MyViewModel.MyCollection = new ObservableCollection<Person>();

        MyViewModel.MyCollection.Add(new Person()
        {
            Age = 22,
            Name = "Nick",
        });

        MyViewModel.MyCollection.Add(new Person()
        {
            Age = 11,
            Name = "Sam",
        });

        MyViewModel.MyCollection.Add(new Person()
        {
            Name = "Kate",
            Age = 15,
        });

        AddEmptyRow(MyViewModel.MyCollection);

        MyViewModel.PropertyChanged += new PropertyChangedEventHandler(MyViewModel_PropertyChanged);
    }

    private void MyViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName.Equals("MayUserAddRows"))
        {
            if (MyViewModel.MayUserAddRows == true) 
            {
                MyViewModel.CanUserAddRows = true;
            }

            if (MyViewModel.MayUserAddRows == false)
            {
                MyViewModel.CanUserAddRows = false;
                AddEmptyRow(MyViewModel.MyCollection);
            }                
        }
    }

    #region AddEmptyRow

    private void AddEmptyRow(ObservableCollection<Person> collection) 
    {
        collection.Add(new Person()
        {
            Name = "",
            Age = 0,
        });
    }

    #endregion

    #region Clear

    private void Clear_Click(object sender, RoutedEventArgs e)
    {
        MyViewModel.MyCollection.Clear();
    }

    #endregion
}

#region ViewModel

public class ViewModel : NotificationObject
{
    #region MyCollection

    public ObservableCollection<Person> MyCollection
    {
        get;
        set;
    }

    #endregion

    #region CanUserAddRows

    private bool _canUserAddRows = false;

    public bool CanUserAddRows
    {
        get
        {
            return _canUserAddRows;
        }

        set
        {
            _canUserAddRows = value;
            NotifyPropertyChanged("CanUserAddRows");
        }
    }

    #endregion

    #region MayUserAddRows

    private bool _mayUserAddRows = false;

    public bool MayUserAddRows
    {
        get
        {
            return _mayUserAddRows;
        }

        set
        {
            _mayUserAddRows = value;
            NotifyPropertyChanged("MayUserAddRows");
        }
    }

    #endregion
}

#endregion

#region Model

public class Person
{
    public string Name
    {
        get;
        set;
    }

    public int Age
    {
        get;
        set;
    }
}

#endregion

#region NotificationObject

public class NotificationObject : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

#endregion
输出

<Window x:Class="ConditionalCanUserAddRows.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:this="clr-namespace:ConditionalCanUserAddRows"
        WindowStartupLocation="CenterScreen"
        Title="MainWindow" Height="300" Width="325">

    <Grid>
        <CheckBox Content="{Binding Path=IsChecked,
                                    RelativeSource={RelativeSource Mode=Self}}"
                  ContentStringFormat="May user add rows - {0}"
                  HorizontalAlignment="Left"
                  VerticalAlignment="Top"
                  IsChecked="{Binding Path=MayUserAddRows}" />

        <Button Content="Clear" 
                VerticalAlignment="Top"
                HorizontalAlignment="Right"
                Click="Clear_Click" />

        <DataGrid Name="SimpleDataGrid"
                  Width="200"
                  Height="200"
                  CanUserResizeColumns="False"                  
                  AutoGenerateColumns="False" 
                  RowHeaderWidth="0" 
                  CanUserAddRows="{Binding Path=CanUserAddRows, Mode=TwoWay}"
                  ItemsSource="{Binding Path=MyCollection}">

            <DataGrid.Columns>
                <DataGridTextColumn Width="1.5*"
                                    Header="Name"
                                    Binding="{Binding Path=Name}" />

                <DataGridTextColumn Header="Age"                                    
                                    Width="1.5*" 
                                    FontSize="14" 
                                    Binding="{Binding Path=Age}" />
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>
public partial class MainWindow : Window
{   
    ViewModel MyViewModel = new ViewModel();

    public MainWindow()
    {
        InitializeComponent();

        this.DataContext = MyViewModel;

        MyViewModel.MyCollection = new ObservableCollection<Person>();

        MyViewModel.MyCollection.Add(new Person()
        {
            Age = 22,
            Name = "Nick",
        });

        MyViewModel.MyCollection.Add(new Person()
        {
            Age = 11,
            Name = "Sam",
        });

        MyViewModel.MyCollection.Add(new Person()
        {
            Name = "Kate",
            Age = 15,
        });

        AddEmptyRow(MyViewModel.MyCollection);

        MyViewModel.PropertyChanged += new PropertyChangedEventHandler(MyViewModel_PropertyChanged);
    }

    private void MyViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName.Equals("MayUserAddRows"))
        {
            if (MyViewModel.MayUserAddRows == true) 
            {
                MyViewModel.CanUserAddRows = true;
            }

            if (MyViewModel.MayUserAddRows == false)
            {
                MyViewModel.CanUserAddRows = false;
                AddEmptyRow(MyViewModel.MyCollection);
            }                
        }
    }

    #region AddEmptyRow

    private void AddEmptyRow(ObservableCollection<Person> collection) 
    {
        collection.Add(new Person()
        {
            Name = "",
            Age = 0,
        });
    }

    #endregion

    #region Clear

    private void Clear_Click(object sender, RoutedEventArgs e)
    {
        MyViewModel.MyCollection.Clear();
    }

    #endregion
}

#region ViewModel

public class ViewModel : NotificationObject
{
    #region MyCollection

    public ObservableCollection<Person> MyCollection
    {
        get;
        set;
    }

    #endregion

    #region CanUserAddRows

    private bool _canUserAddRows = false;

    public bool CanUserAddRows
    {
        get
        {
            return _canUserAddRows;
        }

        set
        {
            _canUserAddRows = value;
            NotifyPropertyChanged("CanUserAddRows");
        }
    }

    #endregion

    #region MayUserAddRows

    private bool _mayUserAddRows = false;

    public bool MayUserAddRows
    {
        get
        {
            return _mayUserAddRows;
        }

        set
        {
            _mayUserAddRows = value;
            NotifyPropertyChanged("MayUserAddRows");
        }
    }

    #endregion
}

#endregion

#region Model

public class Person
{
    public string Name
    {
        get;
        set;
    }

    public int Age
    {
        get;
        set;
    }
}

#endregion

#region NotificationObject

public class NotificationObject : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    protected void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

#endregion
MayUserAddRows=“False”

MayUserAddRows=“True”

在VisualStudio2010下编译的项目,这个例子完全符合MVVM风格

此项目可用


回答得好!谢谢我想再增加3个功能。1) 用户点击清除按钮。然后他选中复选框,此时添加了两行。1具有默认值,另一个为空。当时,我不希望用户有一行带有默认值。2) 当用户取消选中该复选框时,我想清除所有行以及“年龄单元格”列应包含所有年龄的总和。例如,在您答案的最后一张图片中,如果我取消选中复选框,则只有一行应该在那里,并且年龄应该包含1491(因为22+11+15+666+777=1491)。3)我还希望有一个只有两个值的新DataGridComboBoxColumn。i、 e.1)继续2)列表结束。如果用户选择“继续”,则他应该能够在当前行中添加姓名和年龄等详细信息,并且应该能够在填写当前行的详细信息后添加新行。否则,不应允许他在当前行中填写更多详细信息,如姓名和年龄,并且不应在该行之后创建新行。@Vishal:这就是我必须实现的全部功能?对不起,我只做了有问题的事,你自己能做的一切。此外,你必须先在问题中写出来。