使用Cascading Combo框在运行时添加新的DataGrid行?

时间:2012-07-31 19:13:18

标签: wpf mvvm datagrid combobox

如果愿意,请耐心等待,我是WPF MVVM开发的新手。

我正在使用的实用程序(WPF客户端应用程序)包含一个4列数据网格,用于在指定的时间段内向用户显示当前可用的数据。返回的记录可能包含记录完成所需的全部或部分数据。用户应该能够修改缺失的部分或完全添加新行以填充缺失的记录。 4列中的3列包含仅有效选项的组合框。组合框是级联的,因此第一个组合确定组合2和3的内容。第4列是一个简单的价格列。

我设法让网格与默认的返回数据完美配合。 combox正确填充,并将当前记录的值显示为组合中的选定项。

我的问题是添加新行。我一直在努力完成这个内联。这意味着用户单击或选中列表底部的空白行,并将新行添加到集合接受输入。第一个组合填充在空行中,但选择一个值不会将更改级联到其他两个组合。它可以在填充的行中运行。

那有道理吗?我可能会错过一些如此简单的东西,以至于当有人指出它时我会踢自己,但现在我正在撕掉我留下的小头发。

那么,是否可以让新用户通过跳转到下一行来添加一行? 我需要在新行中连接级联组合框吗?

谢谢!

这是我的XAML(在剥离之后基本上是伪代码所以不要误解误导):

<Window x:Class="WpfApplication2.MainWindow"
    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"
    xmlns:local="clr-namespace:WpfApplication2"
    mc:Ignorable="d"
    d:DesignHeight="768"
    d:DesignWidth="1024">

<Window.DataContext>
    <local:MainWindowViewModel />
</Window.DataContext>
<Grid>
    <StackPanel>
        <DataGrid AutoGenerateColumns="False"
                    ItemsSource="{Binding Prices}"
                    SelectedItem="{Binding SelectedPrice}"
                    CanUserAddRows="True">
            <DataGrid.Columns>


                <!--  Price Group  -->
                <DataGridTemplateColumn MinWidth="120"
                                        Header="Price Group">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <ComboBox x:Name="cboPriceGroup"
                                        ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.PriceGroups}"
                                        DisplayMemberPath="Name"
                                        SelectedItem="{Binding PriceGroupObject, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>

                <!--  Option 1  -->
                <DataGridTemplateColumn MinWidth="120"
                                        Header="Option1">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <ComboBox x:Name="cboOption1"
                                        ItemsSource="{Binding PriceGroupObject.Options1}"
                                        DisplayMemberPath="Code"
                                        SelectedValuePath="Id"
                                        SelectedValue="{Binding Option1Id, Mode=TwoWay}" />
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>

                <!--  Option 2  -->
                <DataGridTemplateColumn MinWidth="120"
                                        Header="Option2">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <ComboBox x:Name="cboOption2"
                                        ItemsSource="{Binding PriceGroupObject.Options2}"
                                        DisplayMemberPath="Code"
                                        SelectedValuePath="Id"
                                        SelectedValue="{Binding Option2Id, Mode=TwoWay}" />
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>

                <!--  Price  -->
                <DataGridTemplateColumn MinWidth="120"
                                        Header="Price">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <TextBox x:Name="txtPrice"
                                        Text="{Binding Price, Mode=TwoWay}" />
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>

            </DataGrid.Columns>
        </DataGrid>
    </StackPanel>

</Grid>

这是ViewModel:

    // ViewModelBase implements INotifyPropertyChanged
public class MainWindowViewModel : ViewModelBase    
{
    #region Declarations
    // Comes From Backend.Services
    private IPriceListService _PriceListService;

    private ObservableCollection<Price> _Prices;
    private Price _SelectedPrice;

    private IEnumerable<PriceGroup> _PriceGroups;
    private PriceGroup _SelectedPriceGroup;

    // Same for Options1, Options2

    #endregion

    #region Properties

    public ObservableCollection<Price> Prices
    {
        get { return _Prices; }
        set
        {
            if (_Prices != value)
            {
                _Prices = value;
                OnPropertyChanged("Prices");
            }
        }
    }
    public Price SelectedPrice
    {
        get { return _Price; }
        set
        {
            if (_Price != value)
            {
                _Price = value;
                OnPropertyChanged("SelectedPrice");
            }
        }
    }

    // Same for PriceGroups, Options1, Options2

    #endregion

    #region Constructor
    public MainViewModel()
        : this(new FakePriceListService())
    {

    }
    // Constructor
    public MainViewModel(IPriceListService priceListService)
    {
        _PriceListService = priceListService;
        InitializeViewModel();
    }

    protected override void InitializeViewModel()
    {
        // Test ID
        LoadFuturesPrices(12345);
        LoadPriceGroups();
        base.InitializeViewModel();
    }
    #endregion

    #region Methods

    void LoadFuturesPrices(short FinancialPeriodId)
    { 
        Prices = _PriceListService.GetFuturesPriceList(FinancialPeriodId);
    }

    void LoadPriceGroups()
    {
        PriceGroups = _PriceListService.GetPriceGroups();
    }

    void PriceGroupSelected(string PriceGroupId)
    {
        SelectedPriceGroup = (from p in PriceGroups where p.Name == PriceGroupId select p).SingleOrDefault();
    }
    #endregion

}

0 个答案:

没有答案