使用C#/ XAML,如何根据第一个组合框的选定项更新第二个组合框的ItemsSourceList?

时间:2018-08-11 16:14:50

标签: c# xaml uwp mvvm-light

我已经基于StackOverflow和其他地方的许多示例尝试了许多方法,但是无法使其正常工作。我希望ComboBox B的选择列表根据ComboBox A中的选定项目而有所不同。有人可以帮我确定我做错了什么吗? (我正在使用MVVMLight。)

这是两个组合框的ItemsSources:

private ObservableCollection<SetupSF> _sourceForSFList = new ObservableCollection<SetupSF>();

public ObservableCollection<SetupSF> SourceForSFList
{
    get { return _sourceForSFList; }
    set
    {
        _sourceForSFList = value;
    }
}

private ObservableCollection<SetupSFE> _sourceForSFEList = new ObservableCollection<SetupSFE>();
public ObservableCollection<SetupSFE> SourceForSFEList
{
    get { return _sourceForSFEList; }
    set
    {
        _sourceForSFEList = value;
    }
}

这里是选择器。我尝试使用RelayPropertyChanged,即使它是一个可观察的集合,但没有效果。我已验证通过设置断点来更新列表的内容。该列表会更新,但显然不会通知第二个组合框。 _selectedSF.OwnedSFE本身就是ObservalbleCollection。

public SetupSubfactor SelectedSF
{
    get { return _selectedSF; }
    set 
    {
        _selectedSF = value;
        if (_selectedSF != null)
        {
            SourceForSFEList = _selectedSF.OwnedSFEs;
        }
    } 
}   

这是SF类型的代码。它在ViewModel之外定义。 (这可能是问题吗?

public class SetupSF : ViewModelBase
{
    private string _iD;
    public string Id
    {
        get { return _iD; }
        set
        {
            _iD = value;
            RaisePropertyChanged(nameof(Id));
        }
    }

    private string _sfName;
    public string SFName
    {
        get { return _sfName; }
        set
        {
            _sfName = value;
            RaisePropertyChanged(nameof(SFName));
        }
    }

    public ObservableCollection<SetupSFE> OwnedSFEs { get; set; }
}

这是组合框的XAML:

<ComboBox x:Name="ComboBox A" 
          Width="350" 
          ItemsSource="{x:Bind ViewModel.SourceForSFList}"
          SelectedItem="{x:Bind ViewModel.SelectedSF, Mode=TwoWay}"
          DisplayMemberPath="SFName"/>

<ComboBox x:Name="Comobox B"
          Width="350"
          ItemsSource="{x:Bind ViewModel.SourceForSFEList}"
          SelectedItem="{x:Bind ViewModel.SelectedSFE, Mode=TwoWay}   
          DisplayMemberPath="SFEName"/>

1 个答案:

答案 0 :(得分:1)

我相信您想将SourceForSFEList更改如下:

private ObservableCollection<SetupSFE> _sourceForSFEList = new ObservableCollection<SetupSFE>();
public ObservableCollection<SetupSFE> SourceForSFEList
{
    get { return _sourceForSFEList; }
    set
    {
        _sourceForSFEList.Clear();
        if (value != null)
        {
            foreach (var item in value)
            {
                _sourceForSFEList.Add(item);
            }

        }
    }
}

绑定系统一次调用您的“ get”,并获取_sourceForSFEList指向的初始Collection。稍后,您将_sourceForSFEList更改为指向另一个集合,但是Binding系统对该集合一无所知,因此UI不会更新。绑定系统将UIElement绑定到_sourceForSFEList之后,您需要更新该原始集合,而不是将_sourceForSFEList的值更改为指向新集合。

我尝试推断您的一些原始课程。这是一个有效的示例,我曾经让一个CombBox的选择更新了另一个。

   public class ViewModel
    {
        private ObservableCollection<SetupSF> _sourceForSFList = new ObservableCollection<SetupSF>();

        public ViewModel()
        {
            _sourceForSFList = new ObservableCollection<SetupSF>()
            {
                new SetupSF() { SFName = "One", OwnedSFEs = new ObservableCollection<SetupSFE> () { new SetupSFE() { SFEName = "Three" }, new SetupSFE() { SFEName = "Four" } } },
                new SetupSF() { SFName = "Two", OwnedSFEs = new ObservableCollection<SetupSFE> () { new SetupSFE() { SFEName = "Five" }, new SetupSFE() { SFEName = "Six" } } }
            };
            _sourceForSFEList = new ObservableCollection<SetupSFE>()
            {
                new SetupSFE() { SFEName = "One"},
                new SetupSFE() { SFEName = "Two"}
            };
        }

        private SetupSF _selectedSF;
        public SetupSF SelectedSF
        {
            get { return _selectedSF; }
            set
            {
                _selectedSF = value;
                if (_selectedSF != null)
                {
                    SourceForSFEList = _selectedSF.OwnedSFEs;
                }
            }
        }

        public ObservableCollection<SetupSF> SourceForSFList
        {
            get { return _sourceForSFList; }
            set
            {
                _sourceForSFList = value;
            }
        }

        private ObservableCollection<SetupSFE> _sourceForSFEList = new ObservableCollection<SetupSFE>();
        public ObservableCollection<SetupSFE> SourceForSFEList
        {
            get { return _sourceForSFEList; }
            set
            {
                _sourceForSFEList.Clear();
                if (value != null)
                {
                    foreach (var item in value)
                    {
                        _sourceForSFEList.Add(item);
                    }

                }
            }
        }

    }

    public class SetupSF
    {
        public String SFName { get; set; }
        public ObservableCollection<SetupSFE> OwnedSFEs;
    }

    public class SetupSFE
    {
        public String SFEName { get; set; }
    }

<Page
    x:Class="App7.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App7"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <Page.DataContext>
        <local:ViewModel />
    </Page.DataContext>

    <StackPanel Orientation="Horizontal">
        <ComboBox x:Name="ComboBoxA" 
          Width="350" 
          ItemsSource="{Binding SourceForSFList}"
          SelectedItem="{Binding SelectedSF, Mode=TwoWay}"
          DisplayMemberPath="SFName" Margin="10"/>

        <ComboBox x:Name="ComoboxB"
          Width="350"
          ItemsSource="{Binding SourceForSFEList}"
          SelectedItem="{Binding SelectedSFE, Mode=TwoWay}"   
          DisplayMemberPath="SFEName" Margin="10"/>
    </StackPanel>
</Page>