gpt4 book ai didi

c# - 使用 TabControl 和 MVVM 在 WPF 中正确进行数据绑定(bind)

转载 作者:行者123 更新时间:2023-12-03 10:42:59 25 4
gpt4 key购买 nike

就在我认为我在这方面做得更好的时候,TabControl 现在给我带来了问题。我在 StackOverflow 上阅读了相关文章,但无法让我的简单演示应用程序按照我想要的方式工作。

为了让事情保持集中,我将从一个关于我不明白的事情的问题开始。

我有一个 TabControl,其 TabItems 每个都承载相同的 UserControl。当我将 TabControl.ContentTemplate 的 DataTemplate 设置为我的 UserControl 时,会出现该控件的呈现,但看起来每个选项卡的控件都是相同的。或者它可能根本不与任何选项卡相关联。

主窗口.xaml

<Window x:Class="TabControlMvvm.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:localviews="clr-namespace:TabControlMvvm.Views"
Title="MainWindow" Height="350" Width="525">
<TabControl ItemsSource="{Binding Tabs}" SelectedIndex="{Binding Selected}">
<TabControl.ContentTemplate>
<DataTemplate>
<localviews:PersonMainPanel />
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
</Window>

代码隐藏只是将 ViewModel 设置为其 DataContext:
namespace TabControlMvvm {
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window {
public MainWindow()
{
InitializeComponent();
DataContext = new TabControlMvvm.ViewModels.MainViewModel();
}
}
}

TabItem 的内容应该是另一个 UserControl,PersonMainPanel.xaml:
<UserControl x:Class="TabControlMvvm.Views.PersonMainPanel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:localviews="clr-namespace:TabControlMvvm.Views"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Border BorderBrush="Red" BorderThickness="2">
<TabControl TabStripPlacement="Bottom">
<TabItem Header="Tab 1">
<localviews:MyTabItem />
</TabItem>
<TabItem Header="Tab 2">
<TextBlock Text="This was left blank intentionally" />
</TabItem>
<TabItem Header="Tab 3">
<TextBlock Text="This was also left blank intentionally" />
</TabItem>
</TabControl>
</Border>
</UserControl>

代码隐藏:
namespace TabControlMvvm.Views {
/// <summary>
/// Interaction logic for PersonMainPanel.xaml
/// </summary>
public partial class PersonMainPanel : UserControl {
public PersonMainPanel()
{
InitializeComponent();
}
}
}

和 MainViewModel:
namespace TabControlMvvm.ViewModels {
public class MainViewModel : ViewModelBase {
public ICollectionView Tabs { get; set; }
public int Selected { get; set; }

public class Person
{
public string Name { get; set; }
}

public class DummyController {
public List<Person> Persons { get; private set; }

public DummyController()
{
Persons = new List<Person> {
new Person { Name = "Larry" },
new Person { Name = "Darryl" },
new Person { Name = "Other brother Darryl" }
};
}
}

public DummyController Controller { get; private set; }

public RelayCommand HelloCommand { get; set; }

public MainViewModel()
{
Controller = new DummyController();

/*
IEnumerable<TabItem> tabs = Enumerable.Range( 1, _controller.Persons.Count())
.Select( x => new TabItem { Header = String.Format( "Person {0}", x),
Content = new PersonMainPanel() });
*/
IEnumerable<TabItem> tabs = Enumerable.Range( 1, Controller.Persons.Count())
.Select( x => new TabItem { Header = String.Format( "Person {0}", x)});
Tabs = CollectionViewSource.GetDefaultView( tabs.ToList());
Tabs.MoveCurrentToFirst();

InitializeCommands();
}

private void InitializeCommands()
{
HelloCommand = new RelayCommand( () => { MessageBox.Show( String.Format( "Hello, Person {0} named {1}!",
Selected, Controller.Persons[Selected].Name)); });
}
}
}

PersonMainPanel 托管另一个 TabControl,其中 Tab 1 的内容是 MyTabItem.xaml:
<UserControl x:Class="TabControlMvvm.Views.MyTabItem"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Name:" />
<TextBox Text="{Binding Name}" Width="100" />
</StackPanel>
<Button Command="{Binding HelloCommand}" Content="Say Hello" />
</StackPanel>
</UserControl>

代码隐藏:
namespace TabControlMvvm.Views {
/// <summary>
/// Interaction logic for MyTabItem.xaml
/// </summary>
public partial class MyTabItem : UserControl {
public MyTabItem()
{
InitializeComponent();
}
}
}

在运行时看起来像这样:

enter image description here

到目前为止我遇到的问题:
  • 当我输入人员 1 的姓名,然后单击人员 2 选项卡时,人员 1 的姓名仍然可见,因此我假设控件未正确绑定(bind)数据。我了解 ItemsControls 不会将其 DataContext 传递给他们的 child ,但我不确定如何在不将 View 关联到代码隐藏中的情况下解决此问题。
  • 由于缺少 DataContext,我本来希望在“输出”窗口中出现数据绑定(bind)错误,但我没有收到任何错误。我假设 DataContext 为空,但这不会导致绑定(bind)错误吗?
  • 如何有效地使用 Snoop 来调试此类问题?

  • 这是示例解决方案: http://www.filedropper.com/tabcontrolmvvm

    最佳答案

    这是解决方案:

    在 MainWindow 中修改您的 TabControl 模板,以从您的模型中绑定(bind) Header:

    <TabControl ItemsSource="{Binding Tabs}" SelectedIndex="{Binding Selected}">
    <TabControl.ContentTemplate>
    <DataTemplate>
    <localviews:PersonMainPanel />
    </DataTemplate>
    </TabControl.ContentTemplate>
    <TabControl.ItemContainerStyle>
    <Style TargetType="TabItem">
    <Setter Property="Header" Value="{Binding Header}"/>
    </Style>
    </TabControl.ItemContainerStyle>
    </TabControl>

    在 MyTabItem.xaml 中,设置 UpdateTrigger,因为默认的“OnLostFocus”有时无法保存您的数据:
     <TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}" Width="100" />       

    在 MainViewModel 中修改选项卡的创建,因此它也将具有 Name 属性:
    IEnumerable<TabItem> tabs = Enumerable.Range( 1, Controller.Persons.Count())
    .Select( x => new TabItem { Header = String.Format("Person {0}", x), Name = Controller.Persons[x-1].Name });

    此外,最重要的是,创建自己的 TabItem 类来包含一些有界数据:
    public class TabItem
    {
    public string Name { set; get; }
    public string Header { set; get; }
    }

    关于c# - 使用 TabControl 和 MVVM 在 WPF 中正确进行数据绑定(bind),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46226242/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com