【问题标题】:Combobox Column biding in WPF with MVVM pattern (Galasoft)带有 MVVM 模式的 WPF 中的组合框列绑定 (Galasoft)
【发布时间】:2017-07-14 13:53:04
【问题描述】:

看在上帝的份上,我无法解决这个问题。我确实看到了这个答案:How to Bind data to DataGridComboBoxColumn in DataGrid using MVVM 以及更多关于这个问题的答案,但我不确定我做错了什么。这是我的想法。我有一个绑定到Views 集合的DataGrid。每一行都由类ViewWrapper 的对象表示,ViewWrapper 有一个名为ViewTemplate 的属性,它的类型为ViewWrapper。所以基本上视图包装器可以在其中存储另一个视图包装器。现在,我想将ComboBox 连接到存储在名为ViewTemplates 的变量中的ViewWrapper 对象列表。这在 ViewModel 上可用。它包含所有可能的视图包装器,可以将视图模板属性设置为。现在,我想将 ComboBox 的 SelectedItem 绑定到 DataGrid 行中的 ViewWrapper.ViewTemplate。我无法让这件事发挥作用。

这是我的设置:

XAML:

<UserControl x:Class="GrimshawRibbon.Revit.Views.ViewManager.ViewManagerView"
             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:i="http://schemas.microsoft.com/expression/2010/interactivity"
             xmlns:local="clr-namespace:GrimshawRibbon.Revit.Views.ViewManager"
             xmlns:ex="clr-namespace:GrimshawRibbon.Revit.Wpf.Extensions"
             xmlns:controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
             xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Platform"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="500">
    <UserControl.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
                <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
                <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Colors.xaml" />
                <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/Blue.xaml" />
                <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseLight.xaml" />
                <ResourceDictionary Source="pack://application:,,,/GrimshawRibbon;component/Revit/Wpf/Style/GrimshawTheme.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </UserControl.Resources>
    <Grid>
        <ex:DataGridEx x:Name="dgViews" 
                               Style="{StaticResource AzureDataGrid}" 
                               Margin="10" 
                               AutoGenerateColumns="False" 
                               ItemsSource="{Binding Views, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 
                               CanUserAddRows="False" 
                               IsReadOnly="False" 
                               SelectionMode="Extended" 
                               SelectionUnit="FullRow" 
                               SelectedItemsList="{Binding SelectedViews, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="CellEditEnding">
                    <cmd:EventToCommand PassEventArgsToCommand="True" Command="{Binding CellEditEndingCommand}"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>
            <DataGrid.Columns>
                <DataGridTextColumn Header="Name" Binding="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="*"/>
                <DataGridTextColumn Header="ViewType" Binding="{Binding ViewType}" Width="100" IsReadOnly="True"/>
                <DataGridTextColumn Header="ViewGroup" Binding="{Binding ViewGroup, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="120" IsReadOnly="False"/>
                <DataGridTextColumn Header="ViewSubGroup" Binding="{Binding ViewSubGroup, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="120" IsReadOnly="False"/>
                <DataGridCheckBoxColumn ElementStyle="{DynamicResource MetroDataGridCheckBox}" 
                                        EditingElementStyle="{DynamicResource MetroDataGridCheckBox}" 
                                        Header="OnSheet" 
                                        Binding="{Binding OnSheet, Mode=TwoWay}" 
                                        IsReadOnly="True" 
                                        Width="80">
                </DataGridCheckBoxColumn>
                <DataGridComboBoxColumn Header="ViewTemplate" Width="150" SelectedItemBinding="{Binding WhatDoISetThisTo?}">
                    <DataGridComboBoxColumn.ElementStyle>
                        <Style TargetType="ComboBox">
                            <Setter Property="ItemsSource" Value="{Binding ViewTemplates}"/>
                            <Setter Property="IsReadOnly" Value="True"/>
                        </Style>
                    </DataGridComboBoxColumn.ElementStyle>
                    <DataGridComboBoxColumn.EditingElementStyle>
                        <Style TargetType="ComboBox">
                            <Setter Property="ItemsSource" Value="{Binding ViewTemplates}"/>
                        </Style>
                    </DataGridComboBoxColumn.EditingElementStyle>
                </DataGridComboBoxColumn>
            </DataGrid.Columns>
        </ex:DataGridEx>
    </Grid>
</UserControl>

视图模型:

public class ViewManagerViewModel : ViewModelBaseEx
    {
        public ViewManagerModel Model;
        public ObservableCollection<ViewWrapper> Views { get; private set; }
        public ObservableCollection<ViewWrapper> ViewTemplates { get; private set; }
        public IList SelectedViews { get; set; }
        public RelayCommand<DataGridCellEditEndingEventArgs> CellEditEndingCommand { get; set; }

        public ViewManagerViewModel(Document doc)
        {
            Model = new ViewManagerModel(doc);
            Views = Model.CollectViews();
            ViewTemplates = Model.CollectViewTemplates();
            CellEditEndingCommand = new RelayCommand<DataGridCellEditEndingEventArgs>(args => OnCellEditEnding(args));
        }

        /// <summary>
        /// Logic for handling cell editing events.
        /// </summary>
        /// <param name="e">DataGrid Row object.</param>
        private void OnCellEditEnding(DataGridCellEditEndingEventArgs e)
        {
            var wrapper = e.Row.Item as ViewWrapper;
            switch (e.Column.SortMemberPath)
            {
                case "Name":
                    Model.ChangeName(wrapper);
                    break;
                case "ViewGroup":
                    Model.SetParameter(wrapper, "View Group", wrapper.ViewGroup);
                    break;
                case "ViewSubGroup":
                    Model.SetParameter(wrapper, "View Sub Group", wrapper.ViewSubGroup);
                    break;
                default:
                    break;
            }
        }

        public override void Apply()
        {
            var vw = new List<ViewWrapper>();
            foreach (ViewWrapper v in SelectedViews)
            {
                vw.Add(v);
            }

            Model.Delete(vw);

            // update collection so that rows get deleted in datagrid
            foreach (ViewWrapper i in vw)
            {
                Views.Remove(i);
            }
        }
    }

ViewWrapper 类:

    public abstract class ElementWrapper : ObservableObject
    {
        public virtual object Self { get; set; }
        public virtual ElementId ID { get; set; }
        public virtual string Name { get; set; }
    }



    public class ViewWrapper : ElementWrapper
    {
        public string ViewType { get; set; }
        public bool IsSelected { get; set; }
        public bool OnSheet { get; set; }
        public string ViewGroup { get; set; }
        public string ViewSubGroup { get; set; }
        public ViewWrapper ViewTemplate { get; set; }

    }

【问题讨论】:

    标签: c# wpf mvvm combobox datagrid


    【解决方案1】:

    SelectedItemBinding 属性应绑定到表示当前行的ViewWrapper 对象的ViewTemplate 属性。

    由于ViewTemplates 集合是在视图模型中定义的,您应该使用RelativeSource 绑定才能绑定到它。

    试试这个:

    <DataGridComboBoxColumn Header="ViewTemplate" Width="150" SelectedItemBinding="{Binding ViewTemplate}">
        <DataGridComboBoxColumn.ElementStyle>
            <Style TargetType="ComboBox">
                <Setter Property="ItemsSource" Value="{Binding DataContext.ViewTemplates, RelativeSource={RelativeSource AncestorType=DataGrid}}"/>
                <Setter Property="IsReadOnly" Value="True"/>
            </Style>
        </DataGridComboBoxColumn.ElementStyle>
        <DataGridComboBoxColumn.EditingElementStyle>
            <Style TargetType="ComboBox">
                <Setter Property="ItemsSource" Value="{Binding DataContext.ViewTemplates, RelativeSource={RelativeSource AncestorType=DataGrid}}"/>
            </Style>
        </DataGridComboBoxColumn.EditingElementStyle>
    </DataGridComboBoxColumn>
    

    【讨论】:

    • 这只能让我部分到达那里。我现在可以在下拉列表中看到所有 ViewTemplates,但没有选择任何值。一些行项目已经为 ViewTemplate 分配了一个值,在这种情况下,当组合框的选定项目绑定到它时,它应该从下拉列表中设置正确的值。对吗?
    • 这取决于 ViewTemplate 属性的设置方式。您需要设置一个 ViewWrapper 的实例,该实例存在于视图模型的 ViewTemplates 集合中。
    • 嗯,他们是同一个班级。如果我覆盖该包装类上的Equals 方法会怎样。这是否会告诉它它们是同一个实例,因为是的,它们都是单独实例化的,所以我可以看到它如何认为它们不是同一个对象。
    • 确实如此!谢谢你的帮助。它现在似乎一切正常。我只需要从 Metro 图​​书馆恢复样式。我应该可以从动态资源中设置它吧?
    猜你喜欢
    • 2015-09-15
    • 1970-01-01
    • 2021-10-11
    • 2015-07-11
    • 2015-04-27
    • 2014-07-30
    • 2015-07-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多