Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 获取视图模型(wpf)中选定的选项卡_C#_Wpf_Mvvm_Tabs_Viewmodel - Fatal编程技术网

C# 获取视图模型(wpf)中选定的选项卡

C# 获取视图模型(wpf)中选定的选项卡,c#,wpf,mvvm,tabs,viewmodel,C#,Wpf,Mvvm,Tabs,Viewmodel,我有一个主视图,它有一个选项卡控件。选择选项卡后,它将调用相应的视图进行显示。我在视图模型中有一个函数,它必须知道选择了哪个选项卡来执行操作。我如何做到这一点?视图模型如何知道选择了哪个选项卡?您可以使用选择器基类提供的SelectionChanged事件。SelectionChangedEventArgs将包含新选择(和取消选择)的项目。或者,可以将选择器基类的SelectedItem绑定到ViewModel中的属性,然后在setter中执行一些逻辑 一般来说,将特定于视图的对象传递给View

我有一个主视图,它有一个选项卡控件。选择选项卡后,它将调用相应的视图进行显示。我在视图模型中有一个函数,它必须知道选择了哪个选项卡来执行操作。我如何做到这一点?视图模型如何知道选择了哪个选项卡?

您可以使用选择器基类提供的SelectionChanged事件。SelectionChangedEventArgs将包含新选择(和取消选择)的项目。或者,可以将选择器基类的SelectedItem绑定到ViewModel中的属性,然后在setter中执行一些逻辑


一般来说,将特定于视图的对象传递给ViewModels被认为是违反MVVM的行为——它将UI框架(本例中为WPF)与更通用的ViewModel逻辑紧密耦合。更好的方法是将事件处理程序放在UI代码中,然后在其后面适当地作用于视图模型,但不将视图对象作为参数传递。

下面是一个简单的示例

您应该将选项卡的ItemsSource绑定到ObservaleCollection,这样就可以保存带有应创建选项卡信息的模型

以下是表示选项卡页面的VM和模型:

public class ViewModel
{
    public ObservableCollection<TabItem> Tabs { get; set; }
    public ViewModel()
    {
        Tabs = new ObservableCollection<TabItem>();
        Tabs.Add(new TabItem { Header = "One", Content = "One's content" });
        Tabs.Add(new TabItem { Header = "Two", Content = "Two's content" });
    }
}
public class TabItem
{
    public string Header { get; set; }
    public string Content { get; set; }
}
公共类视图模型
{
公共ObservableCollection选项卡{get;set;}
公共视图模型()
{
Tabs=新的ObservableCollection();
Tabs.Add(新的TabItem{Header=“One”,Content=“One's Content”});
Tabs.Add(新的TabItem{Header=“Two”,Content=“Two's Content”});
}
}
公共类选项卡项
{
公共字符串头{get;set;}
公共字符串内容{get;set;}
}
下面是视图和虚拟机绑定

<Window x:Class="WpfApplication12.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
    <ViewModel
        xmlns="clr-namespace:WpfApplication12" />
</Window.DataContext>
<TabControl
ItemsSource="{Binding Tabs}">
<TabControl.ItemTemplate>
    <!-- this is the header template-->
    <DataTemplate>
        <TextBlock
            Text="{Binding Header}" />
    </DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
    <!-- this is the body of the TabItem template-->
    <DataTemplate>
        <----- usercontrol namespace goes here--->
    </DataTemplate>
</TabControl.ContentTemplate>


来源:

在视图中,您将SelectedIndex属性放在TabControl上:

xmlns:cal="http://www.caliburnproject.org"

<TabControl cal:Message.Attach="[SelectionChanged] = [OnTabSelectionChanged()]"
                    SelectedIndex="{Binding SelectedIndexTab}">
            <TabItem Header="Tab 1"/>
            <TabItem Header="Tab 2"/>
</TabControl>
在本例中,我使用Caliburn捕获TabControl的SelectionChange事件。

非常简单:

<Window x:Class="WpfApplication2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication2"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <local:TestViewModel x:Key="MainViewModel"/>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="50"/>
        </Grid.RowDefinitions>
        <TabControl DataContext="{StaticResource MainViewModel}" 
                    SelectedIndex="{Binding Selected}" 
                    Grid.Row="0" 
                    x:Name="TestTabs">
            <TabItem Header="Section 1"/>
            <TabItem Header="Section 2"/>
            <TabItem Header="Section 3"/>
        </TabControl>
        <Button Content="Check 
                Selected Index" 
                Grid.Row="1" 
                x:Name="TestButton" 
                Click="TestButton_OnClick"/>
    </Grid>
</Window>
这将实现INotifyPropertyChanged,以便视图将向其注册。在这里的处理程序中,我输出Selected的值,以在您更改它们时显示

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void TestButton_OnClick(object sender, RoutedEventArgs e)
    {
        var vm = TestTabs.DataContext as TestViewModel;
        MessageBox.Show(string.Format("You selected tab {0}", vm.Selected));
    }
}

这将获取viewmodel,然后向我们显示属性实际上已更新。

我认为您可以将选项卡控件的选定属性绑定到viewmodel中的属性,然后在那里访问它。它将知道选择了什么,因为。。。这就是模型绑定所做的:)谢谢。我将尝试一下。我在下面提供了一个示例。在某些情况下,SelectedIndex是一种不好的处理方法。如果您有一个表示选项卡的模型(这些模型的集合绑定到选项卡控件的ItemsSource),则只需将SelectedItem绑定到ViewModel。通过SelectedIndex来回转换是浪费时间。没错,在该处理程序中收集所需的信息,然后将其传递给DataContext(VM)上的方法。几天前我开始使用mvvm,但我仍在努力。欢迎光临!MVVM肯定需要一些时间来适应——数据所属位置的细节并不琐碎。我的要求略有不同,但这个解决方案正是医生所要求的,一切都一样。不错!您好@apo,我正在使用这个解决方案,但我不知道为什么,在选择最后一个选项卡时,会无限调用OnTabSelectionChanged()事件。
class TestViewModel : INotifyPropertyChanged
{
    private int _selected;
    public int Selected
    {
        get { return _selected; }
        set
        {
            _selected = value;
            OnPropertyChanged("Selected");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged(string property)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(property));
        }
    }
}
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void TestButton_OnClick(object sender, RoutedEventArgs e)
    {
        var vm = TestTabs.DataContext as TestViewModel;
        MessageBox.Show(string.Format("You selected tab {0}", vm.Selected));
    }
}