WPF中DataGrid中的条件CanUserAddRows

时间:2014-04-04 19:05:23

标签: c# wpf xaml datagrid

假设我有一个ComboBox,如:

<ComboBox SelectedValue="{Binding DataContext.CanUserAddMultipleRows, 
                                  RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Page}},
                                 Converter={StaticResource yesNoToBooleanConverter}}">
    <ComboBoxItem>Yes</ComboBoxItem>
    <ComboBoxItem>No</ComboBoxItem>
</ComboBox>

这是转换器:

public class YesNoToBooleanConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (!(value == null || value == DependencyProperty.UnsetValue))
        {
            if ((bool)value == true)
            {
                return "Yes";
            }
            else
            {
                return "No";
            }
        }
        else
        {
            return "No";
        }
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (!(value == null || value == DependencyProperty.UnsetValue))
        {
            if (((ComboBoxItem)value).Content.ToString() == "Yes")
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        else
        {
            return false;
        }
    }
}

现在我有一个DataGrid:

<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的新手。所以,我问了这个问题。

1 个答案:

答案 0 :(得分:2)

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

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

ViewModel中的属性通过NotificationObject实现INotifyPropertyChanged接口。他有一个事件PropertyChangedEventHandler(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>

<强> Code-behind

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

<强> Output

MayUserAddRows="False"

enter image description here

MayUserAddRows="True"

enter image description here

在Visual Studio 2010下编译的项目,此示例完全符合MVVM样式。

  

此项目可用here