我可以在 1 个应用程序中拥有同一个 UserControl 的多个实例吗?

Jie*_*eng 3 c# wpf user-controls tabcontrol mvvm

我正在创建一个文本编辑器类型应用程序。我可以通过选项卡打开多个编辑器。在我的第一次尝试中,我使用简单的TextBoxes 来编辑文本。一切正常。然后我创建了一个UserControl封装文本框+按钮来执行文本操作,例如。粗体/斜体等。我发现当我打开不同的标签时,它们都包含相同的内容。例如。在 Tab1 中,我输入将出现在所有选项卡中的“hello world”。即使它们在不同的标签中,也没有“分离”

<Window.Resources>
    <DataTemplate DataType="{x:Type vm:EditorTabViewModel}">
        <me:MarkdownEditor />
    </DataTemplate>
</Window.Resources>
Run Code Online (Sandbox Code Playgroud)

然后我作为测试,尝试了一个文本框和用户控件,看看我是否有同样的问题。

<Window.Resources>
    <DataTemplate DataType="{x:Type vm:EditorTabViewModel}">
        <StackPanel>
            <me:MarkdownEditor Text="{Binding Content}" Height="360" />
            <TextBox Text="{Binding Content}" Height="360" />
        </StackPanel>
    </DataTemplate>
</Window.Resources>
Run Code Online (Sandbox Code Playgroud)

然后我发现了一些奇怪的事情。有了一个新文档,其中的内容应该是什么,我MarkdownEditor的文本框中有“System.Windows.Controls.Grid”,因为它绑定了一个网格到文本。文本简单TextBox按预期工作。此外,我仍然遇到相同的问题,UserControl应用程序中的所有s都具有相同的内容。

XAML 用于 UserControl

<UserControl x:Class="MarkdownEditMVVM.Controls.MarkdownEditor.MarkdownEditor" ...>
    <Grid>
        <ToolBar Grid.Row="0">
            <Button Command="{x:Static local:Commands.PreviewCommand}">
                <Image Source="../../Images/16/zoom.png" />
            </Button>
            <!-- more buttons -->
        </ToolBar>
        <TextBox Grid.Row="1" x:Name="txtEditor" AcceptsReturn="True" Text="{Binding Path=Text, UpdateSourceTrigger=PropertyChanged}" />
    </Grid>
</UserControl>
Run Code Online (Sandbox Code Playgroud)


更新

我发现这与我在选项卡绑定到的选项卡中呈现用户控件的方式有关 ObservableCollection<TabViewModel>

假设我有一个TabViewModel甚至只是一个空类

public class TabViewModel {}
Run Code Online (Sandbox Code Playgroud)

然后在我的窗口

public partial class Window1 : Window
{
    protected ObservableCollection<TabViewModel> _tabs;
    protected ICollectionView _tabsCollectionView;

    public Window1()
    {
        InitializeComponent();
        this.DataContext = this;
        _tabs = new ObservableCollection<TabViewModel>();
        _tabs.Add(new TabViewModel());
        _tabs.Add(new TabViewModel());
        _tabsCollectionView = CollectionViewSource.GetDefaultView(_tabs);
    }

    public ICollectionView Tabs
    {
        get { return _tabsCollectionView; }            
    }
}
Run Code Online (Sandbox Code Playgroud)

XAML

<TabControl ItemsSource="{Binding Tabs}" IsSynchronizedWithCurrentItem="True">
    <TabControl.ItemTemplate>
        <DataTemplate>
            <TextBlock />
        </DataTemplate>
    </TabControl.ItemTemplate>
    <TabControl.ContentTemplate>
        <DataTemplate>
            <TextBox />
        </DataTemplate>
    </TabControl.ContentTemplate>
</TabControl>
Run Code Online (Sandbox Code Playgroud)

我创建了一个简单的 Visual Studio Project 托管 @ mediafire 来说明这个问题。我有一种感觉,它与TabViewModels 或 Tab 数据模板有关


更新 2

我通过添加另一个选项卡控件进一步测试了用户控件问题,这次没有 TabViewModel

<TabControl Grid.Column="1">
    <TabItem Header="Tab 1">
        <TextBox />
    </TabItem>
    <TabItem Header="Tab 2">
        <TextBox  />
    </TabItem>
</TabControl>
Run Code Online (Sandbox Code Playgroud)

一切正常。更新也发布到mediafire


更新 3

又做了一个发现。这一次,我用绑定进行了测试。一切顺利……

<TabControl Grid.Column="2" ItemsSource="{Binding Tabs}" IsSynchronizedWithCurrentItem="True">
    <TabControl.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding TabTitle}" />
        </DataTemplate>
    </TabControl.ItemTemplate>
    <TabControl.ContentTemplate>
        <DataTemplate>
            <TextBox Text="{Binding Text}" />
        </DataTemplate>
    </TabControl.ContentTemplate>
</TabControl>
Run Code Online (Sandbox Code Playgroud)

更新也发布在@mediafire


更新 4

好的,现在我做了一组更完整的测试

替代文字

  • 第 0 行,第 0 列:TextBox,标签绑定到ObservableCollection<TabViewModel>。没有绑定TextBox。观察到的问题
  • 第 0 行,第 1 列:文本框、普通 TabItems、未绑定到的选项卡ObservableCollection<TabViewModel>。无绑定TextBox。没问题
  • 第 0 行,第 2 列:文本框,标签绑定到ObservableCollection<TabViewModel>。没有绑定TextBox。没问题
  • 第 1 行,第 0 列:UserControl,标签绑定到ObservableCollection<TabViewModel>。没有绑定UserControl。观察到的问题
  • 第 1 行,第 2 列:UserControl,绑定到ObservableCollection<TabViewModel>. 的绑定UserControl。观察到问题。文本绑定不起作用

更新@mediafire

Ste*_*rex 5

响应更新的大编辑

通过执行以下步骤,我可以让您的 mediafire 示例正常工作:

  1. Text从您的用户控件中删除依赖项属性- 您不需要它
  2. 将您的ContentTemplate上更改TabControl为以下。这会导致将UserControl.DataContext属性设置为选项卡项DataContext

     <DataTemplate>
          <local:UserControl1 />
     </DataTemplate>
    
    Run Code Online (Sandbox Code Playgroud)
  3. 将您UserControl的更改为以下。这将Text属性绑定到UserControl.DataContext.Text属性。

    <TextBox Text="{Binding Text}" />
    
    Run Code Online (Sandbox Code Playgroud)
  4. this.DataContext = this从构造函数中删除该行UserControl1- 这显然将替换DataContext用户控件的 。

这导致选项卡与您上传的示例应用程序中的预期值正确绑定


原答案

您可以有多个 a 实例UserControl- 这不是您的问题。

您所看到的“System.Windows.Controls.Grid”文本的原因是因为在你的UserControl你的绑定Text属性this.DataContext.Text,而不是this.Text-属性UserControl

我认为您想要做的是TextBox将用户控件中的绑定更改为:

<TextBox Grid.Row="1" x:Name="txtEditor" AcceptsReturn="True"
Text="{Binding Path=Text,
        UpdateSourceTrigger=PropertyChanged,
        RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type me:MarkDownEditor}}}" />
Run Code Online (Sandbox Code Playgroud)

注意:这依赖于me被设置为指向您MarkDownEditor所在位置的命名空间