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

C# 我可以在一个应用程序中拥有同一UserControl的多个实例吗?,c#,wpf,user-controls,mvvm,tabcontrol,C#,Wpf,User Controls,Mvvm,Tabcontrol,我正在创建一个文本编辑器类型的应用程序。我可以通过选项卡打开多个编辑器。在我的第一次尝试中,我使用简单的TextBoxes来编辑文本。一切正常。然后我创建了一个UserControl来封装文本框+按钮,以执行文本操作,例如粗体/斜体等。我发现,当我打开不同的选项卡时,它们都包含相同的内容。在选项卡1中,我输入将出现在所有选项卡中的“hello world”。即使它们位于不同的选项卡中,也没有“分离” <Window.Resources> <DataTemplate Da

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

<Window.Resources>
    <DataTemplate DataType="{x:Type vm:EditorTabViewModel}">
        <me:MarkdownEditor />
    </DataTemplate>
</Window.Resources>

更新 我发现这与我在选项卡中呈现用户控件的方式有关,其中选项卡绑定到
ObservableCollection

假设我有一个
选项卡视图模型
,即使只是一个空类

public class TabViewModel {}
然后在我的窗口中

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; }            
    }
}
一切正常。更新也发布到


更新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>

更新也发布了@


更新4 现在我做了一套更完整的测试

  • 第0行,第0列:
    文本框
    ,绑定到
    可观察集合的选项卡
    文本框
    没有绑定。观察到的问题
  • 第0行第1列:文本框,普通选项卡项,未绑定到
    可观察集合的选项卡
    文本框
    没有绑定。没问题
  • 第0行,第2列:文本框,绑定到
    observedcollection
    的选项卡。
    文本框
    没有绑定。没问题
  • 第1行,第0列:
    UserControl
    ,绑定到
    observeCollection
    的选项卡。
    UserControl
    没有绑定。观察到的问题
  • 第1行第2列:
    UserControl
    ,绑定到
    observeCollection
    的选项卡。
    UserControl
    的绑定。观察到问题。文本绑定不起作用

更新@

大编辑以响应更新

我可以通过以下步骤使您的mediafire示例正常工作:

  • 从用户控件中删除dependency属性
    Text
    ——您不需要它
  • 选项卡Control
    上的
    内容模板更改为以下内容。这导致将
    UserControl.DataContext
    属性设置为选项卡项
    DataContext

     <DataTemplate>
          <local:UserControl1 />
     </DataTemplate>
    
  • UserControl1
    的构造函数中删除行
    this.DataContext=this
    ——这显然将替换用户控件的
    DataContext

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


    原始答案

    您可以有一个
    用户控件的多个实例
    ——这不是您的问题

    您之所以看到“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}}}" />
    
    
    

    注意:这取决于
    me
    名称空间的设置,该名称空间指向
    MarkDownEditor
    所在的位置

    您可能对Writer示例应用程序感兴趣。它展示了如何通过应用MVVM模式实现具有多个选项卡支持的文本处理应用程序。

    hmm,我试过了,得到了一个StackOverflow异常。我仍然没有真正理解数据上下文问题。。。可能是因为我从未使用过
    RelativeSource
    tooth这是我的错误-我绑定到
    TextBlock
    上的属性,而不是
    MarkDownEditor
    :s-Post编辑以更正问题嗯,奇怪的是,我仍然遇到相同的网格问题。。。我还尝试创建一个自定义控件,在一个干净的应用程序中创建更多的基本控件,我没有遇到这样的问题。。。一定是在什么地方做错了什么事,你对这些问题有什么建议吗?随着我的发展,我不知何故引入了wierd bug,尽管它们单独工作正常。当我只有一个用户控件时,它工作得很好。我是否应该重写所有内容,然后一次复制并粘贴一个功能?不幸的是,WPF应用程序中的调试行为通常有点棘手,因为您通常无法设置断点。如果我得到的是您这样的行为,我通常会将属性的绑定更改为尽可能简单的内容(例如,
    {binding}
    ),并查看生成的值,然后从中开始工作。您还可以在
    绑定
    上设置一个
    IValueConverter
    ,如果您确实遇到困难,可以在其中指定一个断点……请参阅更新,我认为问题不在于绑定,我删除了所有绑定,但仍然存在相同的问题。
    <TabControl Grid.Column="1">
        <TabItem Header="Tab 1">
            <TextBox />
        </TabItem>
        <TabItem Header="Tab 2">
            <TextBox  />
        </TabItem>
    </TabControl>
    
    <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>
    
     <DataTemplate>
          <local:UserControl1 />
     </DataTemplate>
    
    <TextBox Text="{Binding Text}" />
    
    <TextBox Grid.Row="1" x:Name="txtEditor" AcceptsReturn="True"
    Text="{Binding Path=Text,
            UpdateSourceTrigger=PropertyChanged,
            RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type me:MarkDownEditor}}}" />