在 WPF 中开始时绑定所有选项卡项视图模型

Posted

技术标签:

【中文标题】在 WPF 中开始时绑定所有选项卡项视图模型【英文标题】:Bind all Tab item view model at start in WPF 【发布时间】:2014-08-25 03:51:27 【问题描述】:

我有一个带有 2 个选项卡的应用程序,它们是带有 MVVM 的 WPF 中的 PersonUser Management。现在的问题是,当我点击 Person Mag 选项卡 时,PersonViewModel 将绑定到 Person Mag ViewUser Mag em> 和上面提到的情况一样。

如何使 PersonUser Mag tab 在应用程序启动时绑定其视图模型(两者同时为自己的视图绑定视图模型)而不是绑定单击该选项卡时的视图模型。

XAML

 <DockPanel LastChildFill="True">
    <TabControl TabStripPlacement="Left" DockPanel.Dock="Left" Margin="5">
        <TabItem Width="190" Margin="1">
            <TabItem.Header>
                <StackPanel Orientation="Horizontal">
                    <Image Source="/Images/Person-Management-Icon.png" Width="32" Height="32" />
                    <TextBlock Text="Person Mangement" Margin="5,0,0,0" VerticalAlignment="Center" />
                </StackPanel>
            </TabItem.Header>
            <TabItem.ContentTemplate>
                <DataTemplate>
                    <ptab:PersonManagementView />
                </DataTemplate>
            </TabItem.ContentTemplate>
        </TabItem>
        <TabItem Margin="1">
            <TabItem.Header>
                <StackPanel Orientation="Horizontal">
                    <Image Source="/Images/User-Management-Icon.png" Width="32" Height="32" />
                    <TextBlock Text="User Mangement" Margin="5,0,0,0" VerticalAlignment="Center" />
                </StackPanel>
            </TabItem.Header>
            <TabItem.ContentTemplate>
                <DataTemplate>
                    <ptab:UserManagementView />
                </DataTemplate>
            </TabItem.ContentTemplate>
        </TabItem>
    </TabControl>
</DockPanel>

PersonManagement XAML

<!--View Model Section-->
<UserControl.DataContext>
    <vm:PersonViewModel />
</UserControl.DataContext>
<!--End View Model Section-->

<!--Resources Section-->
<UserControl.Resources>
    <ResourceDictionary Source="../Resources/ResourceDictionary.xaml" />
</UserControl.Resources>
<!--End Resources Section-->

<DockPanel Name="Person_Management_View">
    <TabControl DockPanel.Dock="Top">
        <TabItem>
            <TabItem.Header>
                <StackPanel Orientation="Horizontal">
                    <Image Source="/Images/Person-Creation-Icon.png" Width="24" Height="24" />
                    <TextBlock Text="Person Creation" Margin="5,0,0,0" VerticalAlignment="Center" />
                </StackPanel>
            </TabItem.Header>
            <Grid>
                <Grid.RowDefinitions>
                    <!--Name-->
                    <RowDefinition Height="Auto" />
                    <!--Gender-->
                    <RowDefinition Height="Auto" />
                    <!--Department-->
                    <RowDefinition Height="Auto" />
                    <!--Error Message-->
                    <RowDefinition Height="25" />
                    <!--Save Button-->
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="100" />
                    <ColumnDefinition Width="50" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>

                <!--Name Section-->
                <Label Grid.Row="0" Grid.Column="0" Content="Name"/>
                <Label Grid.Row="0" Grid.Column="1" Content=":"/>
                <TextBox Name="txtPersonName" Grid.Row="0" Grid.Column="2"  Margin="4">
                    <TextBox.Text>
                        <Binding Path="PersonObject.Name" UpdateSourceTrigger="PropertyChanged" >
                            <Binding.ValidationRules>
                                <r:PersonNameRule ValidatesOnTargetUpdated="True" />
                            </Binding.ValidationRules>
                        </Binding>
                    </TextBox.Text>
                </TextBox>
                <!--End Name Section-->

                <!--Gender Section-->
                <Label Grid.Row="1" Grid.Column="0" Content="Gender"/>
                <Label Grid.Row="1" Grid.Column="1" Content=":"/>
                <ComboBox Grid.Row="1" Grid.Column="2"  Margin="4"  ItemsSource="Binding GenderList" SelectedItem="Binding PersonObject.Gender"/>
                <!--End Gender Section-->

                <!--Department Section-->
                <Label Grid.Row="2" Grid.Column="0" Content="Department" />
                <Label Grid.Row="2" Grid.Column="1" Content=":"/>
                <ComboBox Grid.Row="2" Grid.Column="2" Margin="4" ItemsSource="Binding DepartmentList" SelectedItem="Binding PersonObject.DepartmentName" />
                <!--End Department Section-->

                <!--Error Message Section-->
                <TextBlock Grid.Row="3" Grid.Column="2" Margin="4,4,4,0" Visibility="Binding ElementName=txtPersonName, Path=(Validation.Errors), Converter=StaticResource toVisibilityConverter" Style="StaticResource RedTextBlock">
                    <TextBlock.Text>
                        <Binding ElementName="txtPersonName" Path="(Validation.Errors).CurrentItem.ErrorContent"/>
                    </TextBlock.Text>
                </TextBlock>
                <!--End Error Message Section-->

                <!--Save Button Section-->
                <Button Grid.Row="4" Grid.Column="2"  HorizontalAlignment="Right" MinWidth="100" Margin="4,0,4,4" Content="Save" Command="Binding CreatePersonCommand">
                    <Button.Style>
                        <Style TargetType="x:Type Button">
                            <Setter Property="IsEnabled" Value="false" />
                            <Style.Triggers>
                                <MultiDataTrigger>
                                    <MultiDataTrigger.Conditions>
                                        <Condition Binding="Binding ElementName=txtPersonName, Path=(Validation.HasError)" Value="false" />
                                    </MultiDataTrigger.Conditions>
                                    <Setter Property="IsEnabled" Value="true" />
                                </MultiDataTrigger>
                            </Style.Triggers>
                        </Style>
                    </Button.Style>
                </Button>
                <!--End Save Button Section-->

            </Grid>
        </TabItem>
    </TabControl>

    <!--Person Data Section-->
    <DataGrid Name="PersonDataGrid" DockPanel.Dock="Bottom" AutoGenerateColumns="False" IsReadOnly="True" SelectionMode="Single" ColumnWidth="*" ItemsSource="Binding PersonList">
        <DataGrid.Columns>
            <DataGridTextColumn Header="Id" Binding="Binding PersonID" />
            <DataGridTextColumn Header="Name" Binding="Binding Name" />
            <DataGridTextColumn Header="Gender" Binding="Binding Gender, Converter=StaticResource emptyStringConverter" />
            <DataGridTextColumn Header="Department" Binding="Binding DepartmentName, Converter=StaticResource emptyStringConverter" />
            <DataGridTemplateColumn>
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <Button IsEnabled="Binding Selected, Converter=StaticResource oppositeBoolConverter" Command="Binding DataContext.DeletePersonCommand, RelativeSource=RelativeSource AncestorType=x:Type DataGrid" CommandParameter="Binding PersonID" Style="StaticResource TransparentButton">
                            <Image Source="Binding Selected, Converter=StaticResource deleteImageConverter" Width="16" Height="16"/>
                        </Button>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
            <DataGridTemplateColumn>
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <Button Command="Binding DataContext.ViewPersonCommand, RelativeSource=RelativeSource AncestorType=x:Type DataGrid" CommandParameter="Binding PersonID" Style="StaticResource TransparentButton">
                            <Image Source="/Images/Update-Icon.png" Width="16" Height="16"/>
                        </Button>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
    </DataGrid>
    <!--End Person Data Section-->

</DockPanel>

【问题讨论】:

贴出绑定数据的代码 @user1219310 嗨,请告诉我们,为什么在用户管理选项卡上时需要加载人员视图模型。 Navigation through Views @Sajeetharan 我用于绑定的 XAML 代码 @Eldho erm,因为我有剪贴板功能,当我单击复制到剪贴板按钮时,将复制人员和用户详细信息。 因此,我需要 Person 和 User 选项卡在应用程序首次启动时绑定他们自己的视图模型 【参考方案1】:

试试这个

将 Loaded 事件添加到 TabControl

<TabControl TabStripPlacement="Left" DockPanel.Dock="Left" Margin="5" Loaded="Tab_OnLoaded" >

从 xaml 中删除 ContentTemplate 并在代码中分配内容,例如

    void Tab_OnLoaded(object sender, RoutedEventArgs e)
    
        var tabControl = sender as TabControl;
        if (tabControl != null)
        
            for (int i = 0; i < tabControl.Items.Count; i++)
            
                if (i == 1)
                    (tabControl.Items[i] as TabItem).Content = new UserControl2();//Here assign the Usercontrol that you want to set as Content
            
            tabControl.Loaded -= Tab_OnLoaded; // Do this on first time only
        
    

我不认为这是一个好方法。我希望这会有所帮助。

【讨论】:

以上是关于在 WPF 中开始时绑定所有选项卡项视图模型的主要内容,如果未能解决你的问题,请参考以下文章

使用Android ViewPager2在回收器视图中滚动到底部时自动更改选项卡项

处理选项卡选择 SwiftUI

TabControl WPF 问题中与 SelectedItem 的异步绑定

从用户控件中导航WPF选项卡控件?

将视图添加到“更多”选项卡项

带有添加新选项卡按钮 (+) 的 TabControl