【问题标题】:Selected Value in Multi-Column ComboBox多列组合框中的选定值
【发布时间】:2014-02-18 16:41:34
【问题描述】:

我的数据库中有一个名为 Groups 的表,如下所示:

Groups
  |--GroupID
  |--GroupName
  |--ParentID
  |--NatureOfGroupID
  |--EffectID

这是上表的关系图:

我在一个窗口中有一个组合框,其中有两列。这是 xaml:

<ComboBox ItemsSource="{Binding DataContext.GroupNamesWithCorrespondingEffects, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Page}}}"
          SelectedValue="{Binding ParentID}" SelectedValuePath="GroupID">
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding GroupName}" Width="200" />
                <TextBlock Text="{Binding CorrespondingEffect}" />
            </StackPanel>
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>

实际上我想显示 GroupName 及其相应的效果,但是当用户选择任何项目时,我想将 SelectedValue 作为 ParentID。

这里是GroupNameWithCorrespondingEffect.cs的实现

public class GroupNameWithCorrespondingEffect : MainViewModel
{
    private string _groupName;
    public string GroupName 
    {
        get
        {
            return _groupName;
        }
        set
        {
            _groupName = value;
            OnPropertyChanged("GroupName");
        }
    }

    private string _correspondingEffect;
    public string CorrespondingEffect 
    { 
        get 
        {
            return _correspondingEffect;
        } 

        set 
        {
            _correspondingEffect = value;
            OnPropertyChanged("CorrespondingEffect");
        } 
    }
}

这里是 groupsViewModel.cs 的代码

public class GroupsViewModel : MainViewModel
{
    public GroupsViewModel()
    {

        using (Entities db = new Entities())
        {
            GroupNamesWithCorrespondingEffects = (from g in db.Groups
                                                  select new GroupNameWithCorrespondingEffect
                                                  {
                                                      GroupName = g.GroupName,
                                                      CorrespondingEffect = g.Master_Effects.Effect
                                                  }).ToList();

            NaturesOfGroup = (from m in db.Master_NatureOfGroup
                              select m).ToList();
        }

        SaveChangesCommand = new RelayCommand(SaveGroup);

        CurrentGroup = new Group();
    }

    private Group _currentGroup;
    public Group CurrentGroup
    {
        get
        {
            return _currentGroup;
        }

        set
        {
            _currentGroup = value;
            OnPropertyChanged("CurrentGroup");
        }
    }

    private List<GroupNameWithCorrespondingEffect> _groupNamesWithCorrespondingEffects;
    public List<GroupNameWithCorrespondingEffect> GroupNamesWithCorrespondingEffects
    {
        get
        {
            return _groupNamesWithCorrespondingEffects;
        }
        set
        {
            _groupNamesWithCorrespondingEffects = value;
            OnPropertyChanged("GroupNamesWithCorrespondingEffects");
        }
    }

    private List<Master_NatureOfGroup> _naturesOfGroup;
    public List<Master_NatureOfGroup> NaturesOfGroup
    {
        get
        {
            return _naturesOfGroup;
        }
        set
        {
            _naturesOfGroup = value;
            OnPropertyChanged("NaturesOfGroup");
        }
    }

    public ICommand SaveChangesCommand { get; set; }

    private void SaveGroup(object obj)
    {
        Group cGroup = new Group()
        {
            GroupName = CurrentGroup.GroupName,
            **ParentID = CurrentGroup.ParentID,**
            NatureOfGroupID = CurrentGroup.NatureOfGroupID,
            EffectID = CurrentGroup.EffectID
        };

        using (Entities db = new Entities())
        {
            db.Groups.Add(cGroup);
            db.SaveChanges();

            GroupNamesWithCorrespondingEffects = (from g in db.Groups
                                                  select new GroupNameWithCorrespondingEffect
                                                  {
                                                      GroupName = g.GroupName,
                                                      CorrespondingEffect = g.Master_Effects.Effect
                                                  }).ToList();

        }
    }
}

当我调试并在标有 ** .... ** 的行上放置断点时,我总是得到 CurrentGroup.ParentID = null。

更新:

<Page.DataContext>
    <vm:GroupsViewModel />
</Page.DataContext>

<Grid DataContext="{Binding CurrentGroup}">

    <Grid.RowDefinitions>
        <RowDefinition Height="*" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="*" />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>

    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="Auto" />
        <ColumnDefinition Width="0.6*" />
        <ColumnDefinition Width="0.6*" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>

    <TextBlock Grid.Row="1" Grid.Column="1" Text="Name" HorizontalAlignment="Left"/>
    <TextBlock Grid.Row="1" Grid.Column="1" Text=" : " HorizontalAlignment="Right"/>
    <TextBox Grid.Row="1" Grid.Column="2" Grid.ColumnSpan="2" Text="{Binding GroupName}"/>

    <TextBlock Grid.Row="2" Grid.Column="1" Text="Under" HorizontalAlignment="Left"/>
    <TextBlock Grid.Row="2" Grid.Column="1" Text=" : " HorizontalAlignment="Right"/>
    <ComboBox x:Name="cbUnder" Grid.Row="2" Grid.Column="2" Grid.ColumnSpan="2" 
              ItemsSource="{Binding DataContext.GroupNamesWithCorrespondingEffects, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Page}}}"
              SelectedValue="{Binding ParentID}" SelectedValuePath="GroupID">
        <ComboBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding GroupName}" Width="200" />
                    <TextBlock Text="{Binding CorrespondingEffect}" />
                </StackPanel>
            </DataTemplate>
        </ComboBox.ItemTemplate>
    </ComboBox>

    <TextBlock Grid.Row="3" Grid.Column="1" Text="Nature of Group" HorizontalAlignment="Left" Visibility="{Binding Visibility, ElementName=cbNature}"/>
    <TextBlock Grid.Row="3" Grid.Column="1" Text=" : " HorizontalAlignment="Right" Visibility="{Binding Visibility, ElementName=cbNature}"/>
    <ComboBox x:Name="cbNature" Grid.Row="3" Grid.Column="2" Visibility="{Binding SelectedIndex, Converter={StaticResource selectedIndexToVisibilityConverter}, ElementName=cbUnder}"
              ItemsSource="{Binding DataContext.NaturesOfGroup, RelativeSource={RelativeSource AncestorType={x:Type Page}}}" DisplayMemberPath="Nature"
              SelectedValue="{Binding NatureOfGroupID}" SelectedValuePath="NatureOfGroupID"/>

    <StackPanel Grid.Row="5" Grid.Column="4" Orientation="Horizontal">
        <Button Content="Save" Command="{Binding DataContext.SaveChangesCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Page}}}"/>
    </StackPanel>
</Grid>

【问题讨论】:

  • CurrentGroup 没有与 XAML 绑定。你在哪里设置这个?
  • CurrentGroup 绑定到 Combobox 的父 Grid。抱歉,我忘了提到这个问题。
  • 绑定到网格是什么意思?它是如何更新的? Grid 没有任何 SelectedValue 属性。这如何与组合框选定值同步?
  • 请参阅我的问题中的更新以更好地了解 Grid 和 CurrentGroup 之间的绑定。
  • 请参阅问题的最底部。我提到&lt;Grid DataContext="CurrentGroup"&gt;.......的更新的xaml,并且在你提到的行下方的C#中我声明了public Group CurrentGroup。这里 CurrentGroup 的数据类型是 Group,所以我认为它应该自动设置实际属性。如果我犯了一些错误,请给我一个小演示示例来理解。

标签: c# wpf xaml combobox


【解决方案1】:

我可以在您的代码中看到两个问题。

首先你提到了

实际上我想显示 GroupName 及其相应的效果,但是 当用户选择任何项目时,我想将 SelectedValue 设为 父母 ID。

但在组合框声明中,您设置了SelectedValuePath="GroupID"。它应该设置为 ParentID - SelectedValuePath="ParentID"


第二,即使你将SelectedValuePath设置为ParentID,它也不起作用,因为combobox ItemsSource是GroupNameWithCorrespondingEffect的列表,它没有任何属性ParentID在它。

为了使 SelectedValuePath 工作,底层模型类应该具有该属性,因此创建一个属性并像其他两个属性一样从数据库中填充它。

GroupNamesWithCorrespondingEffects = (from g in db.Groups
                             select new GroupNameWithCorrespondingEffect
                             {
                                GroupName = g.GroupName,
                                CorrespondingEffect = g.Master_Effects.Effect,
                                ParentID = g.ParentId
                             }).ToList();

因此,要使您的解决方案发挥作用,您必须解决这两个问题。

【讨论】:

  • 我对你的第一个解决方案有一些问题:如果我设置 SelectedValuePath="ParentID" 那么我应该为 SelectedValue 设置什么值?
  • 这与您为第二个组合框 SelectedValue="{Binding NatureOfGroupID}" SelectedValuePath="NatureOfGroupID" 所做的相同。现在澄清SelectedValue 指向您想要跟踪组合框中选定对象的实际属性实例,SelectedValuePath 表示如果对象绑定到对象,那么哪个属性应该用作 selectedValue 的路径。因此,在您的情况下,两者都是ParentID,就像您为第二个组合框所做的那样。
  • 我已经尝试了您的第二个解决方案,也阅读了您的上述评论并按照您的建议进行了更改,但现在我总是CurrentGroup.ParentID = 1
  • 将断点放在 ParentID 属性的设置器上,并查看通过组合框传递给它的值。您是否还确保在填写 GroupNamesWithCorrespondingEffects 属性时所有值都具有唯一的 ParentID?你的意思是第二种解决方案?我只发布了一个有两个问题的解决方案。您需要同时解决这两个问题。
  • 感谢您的帮助。我明白了。我误解了这个概念。我需要 GroupID 而不是 ParentID。但是我已经按照您在回答中建议的方式解决了它。再次感谢您帮助我并给我时间。
猜你喜欢
  • 2014-09-13
  • 2018-10-24
  • 2011-05-23
  • 2014-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多