一个组合框在WPF Datagrid的过滤另一个组合框(One combo box filterin

2019-08-16 19:35发布

我有中有两个组合框列的数据网格。 第一个组合框是PersonnelTypes的列表。 根据该PersonnelType选择,第二个组合框应填写了资源的匹配列表选择PersonnelType那

问题是,可以说我有两行数据,如果我改变一行的PersonnelType,数据网格将设置为所有资源的ItemSource每排。 我只希望它来过滤,我在行,不是所有的行。

下面是具有组合框DataGrid的部分XAML:

                    <DataGridTemplateColumn  Header="Personnel Type" Width="Auto">
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <Grid>
                                    <ComboBox Name="cmbPersonnelTypes" FontWeight="Bold" ItemsSource="{Binding ViewModel.PersonnelTypes, RelativeSource={RelativeSource AncestorType=Window}}"  SelectedItem="{Binding PersonnelType, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" SelectedValuePath="ID" DisplayMemberPath="Description" SelectionChanged="cmbPersonnelTypes_SelectionChanged" />
                                </Grid>
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>
                    <DataGridTemplateColumn  Header="Name" Width="Auto">
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <Grid>
                                    <ComboBox Name="cmbPersonnelName" FontWeight="Bold" ItemsSource="{Binding ViewModel.ResourcesToChooseFrom, RelativeSource={RelativeSource AncestorType=Window},UpdateSourceTrigger=PropertyChanged}"   SelectedItem="{Binding Resource, Mode=TwoWay}" SelectedValuePath="Refno" DisplayMemberPath="Name" />
                                </Grid>
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn> 

这里是(你需要看到它,以防万一)的XAML整个数据网格:

            <DataGrid AutoGenerateColumns="False" CanUserSortColumns="False" CanUserDeleteRows="True" IsReadOnly="True" Background="LightGray" CanUserAddRows="False" Margin="5" SelectedItem="{Binding SelectedLA_JobPersonnel}" ItemsSource="{Binding LA_Personnel}" Grid.ColumnSpan="4" MouseDoubleClick="DataGrid_MouseDoubleClick_1">
                <DataGrid.Resources>
                    <ViewModels:BindingProxy x:Key="proxy" Data="{Binding}" />
                </DataGrid.Resources>
                <DataGrid.Columns>
                    <DataGridTemplateColumn  Header="Personnel Type" Width="Auto">
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <Grid>
                                    <ComboBox Name="cmbPersonnelTypes" FontWeight="Bold" ItemsSource="{Binding ViewModel.PersonnelTypes, RelativeSource={RelativeSource AncestorType=Window}}"  SelectedItem="{Binding PersonnelType, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" SelectedValuePath="ID" DisplayMemberPath="Description" SelectionChanged="cmbPersonnelTypes_SelectionChanged" />
                                </Grid>
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>
                    <DataGridTemplateColumn  Header="Name" Width="Auto">
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <Grid>
                                    <ComboBox Name="cmbPersonnelName" FontWeight="Bold" ItemsSource="{Binding ViewModel.ResourcesToChooseFrom, RelativeSource={RelativeSource AncestorType=Window},UpdateSourceTrigger=PropertyChanged}"   SelectedItem="{Binding Resource, Mode=TwoWay}" SelectedValuePath="Refno" DisplayMemberPath="Name" />
                                </Grid>
                            </DataTemplate>
                        </DataGridTemplateColumn.CellTemplate>
                    </DataGridTemplateColumn>                            <DataGridTemplateColumn Header="Date Out"  Width="20*" >

                        <DataGridTemplateColumn.CellTemplate>

                            <DataTemplate>

                                <TextBlock Background="LightGray" FontWeight="Bold" Text="{Binding DateOut, Mode=TwoWay, Converter={StaticResource thisNullDateConverter}, StringFormat={}{0:MMM-dd-yyyy hh:ss tt}}">
                                </TextBlock>
                            </DataTemplate>

                        </DataGridTemplateColumn.CellTemplate>

                        <DataGridTemplateColumn.CellEditingTemplate>

                            <DataTemplate>
                                <Toolkit:DateTimePicker Background="LightGray" FontWeight="Bold" Value="{Binding Path=DateOut, Mode=TwoWay, Converter={StaticResource thisNullDateConverter}}" Format="Custom" FormatString="MMM dd yyyy hh:ss tt"></Toolkit:DateTimePicker>

                            </DataTemplate>

                        </DataGridTemplateColumn.CellEditingTemplate>
                    </DataGridTemplateColumn>
                    <DataGridTemplateColumn Header="Date In"  Width="20*">

                        <DataGridTemplateColumn.CellTemplate>

                            <DataTemplate>

                                <TextBlock Background="LightGray" FontWeight="Bold" Text="{Binding DateIn, Mode=TwoWay, Converter={StaticResource thisNullDateConverter}, StringFormat={}{0:MMM-dd-yyyy hh:ss tt}}">
                                </TextBlock>
                            </DataTemplate>

                        </DataGridTemplateColumn.CellTemplate>

                        <DataGridTemplateColumn.CellEditingTemplate>

                            <DataTemplate>
                                <Toolkit:DateTimePicker Background="LightGray" FontWeight="Bold" Value="{Binding Path=DateIn, Mode=TwoWay, Converter={StaticResource thisNullDateConverter}}" Format="Custom" FormatString="MMM dd yyyy hh:ss tt"></Toolkit:DateTimePicker>

                            </DataTemplate>

                        </DataGridTemplateColumn.CellEditingTemplate>
                    </DataGridTemplateColumn>
                </DataGrid.Columns>


            </DataGrid>

这是背后的XAML(xaml.cs)的代码:

    public JobEditorViewModel ViewModel
    {
        get { return viewModel; }
    }

private void cmbPersonnelTypes_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        var combobox = sender as ComboBox;
        if (combobox != null)
        {
            var selectedPersonnelType = combobox.SelectedItem as PersonnelType;
            viewModel.SetResourcesToChooseFrom(selectedPersonnelType);
        }
    }

这是在视图模型的代码:

public BindingList<PersonnelType> PersonnelTypes
{
    get; set;
}
public JobEditorViewModel(int jobid, string region, DataAccessDataContext db, ServiceUserControlViewModel serviceViewModel)
{

    PersonnelTypes = new BindingList<PersonnelType>(_db.PersonnelTypes.OrderBy(p => p.Head).ThenBy(p => p.Description).ToList());

}


private BindingList<Resource> _resourcesToChooseFrom;


public BindingList<Resource> ResourcesToChooseFrom
{
    get { return _resourcesToChooseFrom; }
    set
    {
        _resourcesToChooseFrom = value;
        NotifyPropertyChanged("ResourcesToChooseFrom");
    }
}

public void SetResourcesToChooseFrom(PersonnelType personnelType)
{
   ResourcesToChooseFrom =
        new BindingList<Resource>(_db.Resources.Where(r => r.Head == personnelType.Head && r.Refno > 2).OrderBy(r=>r.Name).ToList());
}

如果您需要查看更多,让我知道

Answer 1:

那么,与从这里的同事在工作中的一些帮助,我们想通了什么,我需要做的。 Multibinding就是答案。 首先,我们那种黑客周围,以使两个组合框,可以在同一列通过将它们两者在网格中,并把电网的一列。 所以,现在这两个组合框可以看到对方,因为他们是在同一个DataGridTemplateColumn。 之前,我们不能让他们看到对方,因为他们是两个独立的DataGridTemplateColumns失去了彼此的范围。

下面是我们在XAML中所做的:

                                <DataGridTemplateColumn  Header="Personnel Type-Name" Width="Auto" >
                                    <DataGridTemplateColumn.CellTemplate>
                                        <DataTemplate>
                                            <Grid >
                                                <Grid.ColumnDefinitions>
                                                    <ColumnDefinition Width="170"/>
                                                    <ColumnDefinition Width="*"/>
                                                </Grid.ColumnDefinitions>

                                                <Border Grid.Column="0" BorderBrush="Black" BorderThickness="1">
                                                    <TextBlock Text="{Binding PersonnelType.Description}"/>
                                                </Border>
                                                <Border Grid.Column="1" BorderBrush="Black" BorderThickness="1">
                                                    <TextBlock  Text="{Binding Resource.Name}"/>
                                                </Border>

                                            </Grid>
                                        </DataTemplate>
                                    </DataGridTemplateColumn.CellTemplate>


                                    <DataGridTemplateColumn.CellEditingTemplate>
                                        <DataTemplate>
                                            <Grid >
                                                <Grid.ColumnDefinitions>
                                                    <ColumnDefinition Width="170"/>
                                                    <ColumnDefinition Width="*"/>
                                                </Grid.ColumnDefinitions>


                                                <ComboBox Name="cmbPersonnelTypes" Grid.Column="0" FontWeight="Bold" ItemsSource="{Binding ViewModel.PersonnelTypes, RelativeSource={RelativeSource AncestorType=Window}, UpdateSourceTrigger=PropertyChanged}" SelectedItem="{Binding PersonnelType, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" SelectedValuePath="ID" DisplayMemberPath="Description" />
                                                <ComboBox Name="cmbPersonnelName" Grid.Column="1"  FontWeight="Bold" SelectedItem="{Binding Resource, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" SelectedValuePath="Refno" DisplayMemberPath="Name" >
                                                    <ComboBox.ItemsSource>
                                                        <MultiBinding Converter="{StaticResource FilteredPersonnelConverter}">
                                                            <Binding Path="ViewModel.AvailablePersonnel" RelativeSource="{RelativeSource AncestorType=Window}"/>
                                                            <Binding Path="SelectedItem" ElementName="cmbPersonnelTypes"/>
                                                            <Binding Path="ViewModel.SelectedGlobalResourceViewOption" RelativeSource="{RelativeSource AncestorType=Window}"/>
                                                        </MultiBinding>
                                                    </ComboBox.ItemsSource>
                                                </ComboBox>

                                            </Grid>
                                        </DataTemplate>
                                    </DataGridTemplateColumn.CellEditingTemplate>

                                </DataGridTemplateColumn>

你会发现有一个ValueConverter在MultiBinding称为FilteredPersonnelConverter。 此值转换器完成所有的过滤我。 下面是该代码:

public class FilteredPersonnelListValueConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        var allResources = values[0] as IList<Resource>;
        var personnelType = values[1] as PersonnelType;
        var selectedGlobalResourceView = values[2] as ResourceViewOption;
        if (personnelType == null)
            return allResources;
        if(selectedGlobalResourceView.ResourceViewTitle=="Regional")
            return allResources.Where(r => r.Head == personnelType.Head && r.Obsolete == false && r.Location.Region.RegionID.Trim()==SettingsManager.OpsMgrSettings.Region.Trim()).OrderBy(r => r.Name).ToList();
        if (selectedGlobalResourceView.ResourceViewTitle == "Local")
            return allResources.Where(r => r.Head == personnelType.Head && r.Obsolete == false && r.LocnID.Trim() == SettingsManager.OpsMgrSettings.LOCNCODE.Trim()).OrderBy(r => r.Name).ToList();

        return allResources.Where(r => r.Head == personnelType.Head &&r.Obsolete==false).OrderBy(r => r.Name).ToList();

    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

因此,如果其他人在做这样的事情,看看Multibinding,它会改变你的生活



Answer 2:

当用户改变在视图中PersonelType下拉列表中,视图模型应该然后过滤资源列表(应更新使用正确的信息的第二下拉框)。

真的是你的视图模型只需要被设置为对视图的变化。 这就是它归结为。

展望这里:

public JobEditorViewModel(int jobid, string region, DataAccessDataContext db, ServiceUserControlViewModel serviceViewModel)
{

    PersonnelTypes = new BindingList<PersonnelType>(_db.PersonnelTypes.OrderBy(p => p.Head).ThenBy(p => p.Description).ToList());

}

它看起来像你在构造函数中设置的企业人事类型,但你不响应用户的变化。 你需要做的是,在PersonelType绑定您的视图模型。

编辑

我现在你正在处理改变选择,请参阅。 不过说真的,我认为这应该在视图模型本身来完成。 特别是因为你实际上从视图访问视图模型做进行更改。

因此,这里是我的VM:

class ViewModel : INotifyPropertyChanged
{
    DispatcherTimer timer = new DispatcherTimer();

    public ViewModel()
    {
        // Create my observable collection
        this.DateTimes = new ObservableCollection<DateTime>();

        // Every second add anothe ritem
        timer.Interval = TimeSpan.FromSeconds(1);
        timer.Tick += new EventHandler(timer_Tick);
        timer.Start();
    }

    void timer_Tick(object sender, EventArgs e)
    {
        // This adds to the collection
        this.DateTimes.Add(DateTime.Now);
    }

    public ObservableCollection<DateTime> DateTimes { get; private set; }

    public event PropertyChangedEventHandler PropertyChanged;
}

而我的观点:

<ListBox ItemsSource="{Binding DateTimes}"/> 

请注意,我不重建集合。 我只设置一次,然后改变它的大小为neccesary。



文章来源: One combo box filtering another combo box in a WPF Datagrid