【问题标题】:WPF ComboBox selection change on TabItem selection changeWPF ComboBox 选择更改 TabItem 选择更改
【发布时间】:2013-03-03 23:15:07
【问题描述】:

我在 MVVM 的选项卡项中有一个组合框。这个选项卡可以在我的应用程序中创建多次(相同的视图、相同的视图模型但不同的实例),所以我可以从一个选项卡切换到另一个选项卡(但它们是相同类型的选项卡)。

它适用于每个 WPF 控件,但使用组合框我有一个奇怪的行为: 焦点选项卡,当它失去焦点时,获取应用程序正在关注的选项卡的组合框的选定项。

如果我从 2 个不同类型的选项卡切换,一切正常,你知道吗?谢谢。

XAML:

<CollectionViewSource x:Key="StatusView" Source="{Binding Path=StatusList}"/>
<ComboBox Name="_spl2Status" Grid.Column="3" Grid.Row="0"
          ItemsSource="{Binding Source={StaticResource StatusView}}"
          SelectedValue="{Binding Path=CurrentSPL2.ID_SPL2_STATUS, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
          SelectedValuePath="FL_TYPE"
          DisplayMemberPath="ID_TYPE">
</ComboBox>

虚拟机:

public List<NullableByteEnumType> StatusList
{
    get
    {
        return (SPC_SPL2.SPL2StatusCollection.Skip(1)).ToList();
    }
}

private SPC_SPL2 _currentSPL2 = null;

public SPC_SPL2 CurrentSPL2
{
    get
    {
        if (_currentSPL2== null)
            Controller.Execute(delegate(IResult result)
            {
                Dictionary<string, object> parameters = new Dictionary<string, object>();
                parameters.Add("FL_ACTIVE", true);
                parameters.Add("ID_SPL2", _itemcode);
                Model.Invalidate(typeof(SPC_SPL2), Filter.GENERIC<SPC_SPL2>(parameters, "ID_SPL2"));
                Model.Include<SPC_SPL2>();

                if (Model.Appendload(result) == false)
                    return false;

                Debug.Assert(Context.SPC_SPL2.Count == 1);
                _currentSPL2= Context.SPC_SPL2.FirstOrDefault();

                return result.Successful;
            });

        return _currentSPL2;
    }
    set
    {
        _currentSPL2= value;
        OnPropertyChanged(() => CurrentSPL2);
    }
}

我的标签是这样处理的:

<Grid>
    <Border Grid.Row="0">
        <ContentControl 
            Content="{Binding Path=Workspaces}" 
            ContentTemplate="{StaticResource MasterWorkspacesTemplate}"
            />
    </Border>
</Grid>

在哪里

 <DataTemplate x:Key="MasterWorkspacesTemplate">
            <TabControl IsSynchronizedWithCurrentItem="True" 
                        BorderThickness="0" 
                        ItemsSource="{Binding}" 
                        SelectedItem="{Binding}"
                        ItemContainerStyleSelector="{StaticResource TabItemTemplate}"
                        />
        </DataTemplate>

和工作区(我的视图模型列表)(T 是继承自 viewModelBase 的类)

 public T CurrentWorkspace
    {
        get { return WorkspacesView.CurrentItem as T; }
    }

    private ObservableCollection<T> _workspaces;
    public ObservableCollection<T> Workspaces
    {
        get
        {
            if (_workspaces == null)
            {
                _workspaces = new ObservableCollection<T>();
                _workspaces.CollectionChanged += _OnWorkspacesChanged;
            }

            return _workspaces;
        }
    }
    protected ICollectionView WorkspacesView
    {
        get
        {
            ICollectionView collectionView = CollectionViewSource.GetDefaultView(Workspaces);
            Debug.Assert(collectionView != null);
            return collectionView;
        }
    }

【问题讨论】:

  • 请添加一些带有ComboBox和绑定VM的视图代码。
  • 我添加了一些代码,提前感谢您的帮助
  • 您能展示一下您是如何初始化视图模型的,以及您使用的是什么 MVVM 框架吗?
  • 这可能是您的选项卡控件以及如何在视图模型中分配值的问题。如果您可以向我们展示完整的 xaml 和视图模型会更好。

标签: c# mvvm combobox tabs selecteditem


【解决方案1】:

我已经重现了您的问题。但我找不到任何问题。请查看下面的代码,您可能会得到解决方案。这是我的解决方案。

MyTab查看模型

public class MyTab : ViewModelBase
{
    #region Declarations

    private ObservableCollection<string> statusList;
    private string selectedStatus;

    #endregion

    #region Properties

    /// <summary>
    /// Gets or sets the header.
    /// </summary>
    /// <value>The header.</value>
    public string Header { get; set; }

    /// <summary>
    /// Gets or sets the content.
    /// </summary>
    /// <value>The content.</value>
    public string Content { get; set; }

    /// <summary>
    /// Gets or sets the status list.
    /// </summary>
    /// <value>The status list.</value>
    public ObservableCollection<string> StatusList
    {
        get
        {
            return statusList;
        }
        set
        {
            statusList = value;
            NotifyPropertyChanged("StatusList");
        }
    }

    /// <summary>
    /// Gets or sets the selected status.
    /// </summary>
    /// <value>The selected status.</value>
    public string SelectedStatus
    {
        get
        {
            return selectedStatus;
        }
        set
        {
            selectedStatus = value;
            NotifyPropertyChanged("SelectedStatus");
        }
    }

    #endregion
}

MainViewModel 视图模型

public class MainViewModel : ViewModelBase
{
    #region Declarations

    private ObservableCollection<MyTab> tabs;
    private MyTab selectedTab;

    #endregion

    #region Properties

    /// <summary>
    /// Gets or sets the tabs.
    /// </summary>
    /// <value>The tabs.</value>
    public ObservableCollection<MyTab> Tabs
    {
        get
        {
            return tabs;
        }
        set
        {
            tabs = value;
            NotifyPropertyChanged("Tabs");
        }
    }

    /// <summary>
    /// Gets or sets the selected tab.
    /// </summary>
    /// <value>The selected tab.</value>
    public MyTab SelectedTab
    {
        get
        {
            return selectedTab;
        }
        set
        {
            selectedTab = value;
            NotifyPropertyChanged("SelectedTab");
        }
    }

    #endregion

    #region Constructors

    /// <summary>
    /// Initializes a new instance of the <see cref="MainViewModel"/> class.
    /// </summary>
    public MainViewModel()
    {
        this.Tabs = new ObservableCollection<MyTab>();

        MyTab tab1 = new MyTab();
        tab1.Header = "tab1";
        tab1.Content = "Tab 1 content";
        ObservableCollection<string> tab1StatusList = new ObservableCollection<string>();
        tab1StatusList.Add("tab1 item1");
        tab1StatusList.Add("tab1 item2");
        tab1StatusList.Add("tab1 item3");
        tab1.StatusList = tab1StatusList;
        tab1.SelectedStatus = tab1StatusList.First();
        this.Tabs.Add(tab1);

        MyTab tab2 = new MyTab();
        tab2.Header = "tab2";
        tab2.Content = "Tab 2 content";
        ObservableCollection<string> tab2StatusList = new ObservableCollection<string>();
        tab2StatusList.Add("tab2 item1");
        tab2StatusList.Add("tab2 item2");
        tab2StatusList.Add("tab2 item3");
        tab2.StatusList = tab2StatusList;
        tab2.SelectedStatus = tab2StatusList.First();
        this.Tabs.Add(tab2);

        this.SelectedTab = tab1;
    }

    #endregion
}

最后这是我的XAML

 <Window x:Class="ComboboxSelectedItem.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:viewModel="clr-namespace:ComboboxSelectedItem.ViewModels"
    Title="MainWindow" Height="350" Width="525">
<Grid Name="mainGrid">

    <Grid.DataContext>
        <viewModel:MainViewModel />
    </Grid.DataContext>

    <TabControl
        ItemsSource="{Binding Tabs, Mode=TwoWay}"
        SelectedItem="{Binding SelectedTab}">

        <TabControl.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding Header}" Margin="0 0 20 0"/>
                </StackPanel>
            </DataTemplate>
        </TabControl.ItemTemplate>

        <!--Content section-->
        <TabControl.ContentTemplate>
            <DataTemplate>
                <Grid>
                    <StackPanel Orientation="Vertical">
                        <TextBlock
                            Text="{Binding Content}" />
                        <ComboBox
                            ItemsSource="{Binding StatusList}"
                            SelectedItem="{Binding SelectedStatus}" />
                    </StackPanel>

                </Grid>
            </DataTemplate>
        </TabControl.ContentTemplate>

    </TabControl>
</Grid>
</Window>

【讨论】:

  • 好吧,我发现了不同之处,我将其添加到我的问题中(重新编辑)
  • 我在一个更简单的应用程序中重现了该错误(因此上传一些代码更容易)。 stackoverflow.com/questions/15531920/…提前谢谢你,如果你想看看它
【解决方案2】:

您确定要创建视图模型的新实例吗?如果不是,则组合框共享相同的 collectionviewsource,这意味着一个组合框的更改将反映在所有组合框中。我自己也有同样的问题。

尝试在代码中声明集合视图源:

CollectionViewSource StatusListViewSource = new CollectionViewSource();
StatusListViewSource.Source = SPL2StatusCollection;

然后在 xaml 中更改绑定到 collectionviewsource:

ItemsSource="{Binding StatusListViewSource.View}"

我是从 vb 转换过来的,所以可能需要一些修改。
这有帮助吗?

【讨论】:

  • 我仍然有同样的错误。而且我确定它们是不同的实例,因为当我加载它们时,它们从数据库中获取了正确的数据(不同),但是当我切换选项卡时,它们会复制数据(并且我检查问题是否不在负载上,但是在标签更改)
  • 对不起,我不知道从哪里开始。我通常开始逐步检查每个程序以了解发生了什么。你能检查一下底层绑定中发生了什么。也许这是一个 UI 问题,其中 viewmodel 中的数据正常但 UI 错误。您是否正在实施 INotifyPropertyChanged?
猜你喜欢
  • 2013-03-10
  • 1970-01-01
  • 2020-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-28
相关资源
最近更新 更多