C#VS:将代码分解为UserControl,使用ObservableCollection,并使用绑定使用它

C#VS:将代码分解为UserControl,使用ObservableCollection,并使用绑定使用它,c#,wpf,xaml,user-controls,C#,Wpf,Xaml,User Controls,我将一些代码分解成UserControls,在使用时绑定哪些参数。我在使用ObservableCollection作为从属属性时遇到了困难 显示困难的示例是一个包含两个DependencyProperty的主窗口的项目: 一个表示字符串(名为“数据”)的 另一个代表可观测集合(命名为“原点”) 和一个UserControl(名为UserControl1)公开两个类似的DependencyProperty(名为resp.“Liste”和“Noun”) 主窗口包含文本绑定到“数据”的文本块和Item

我将一些代码分解成UserControls,在使用时绑定哪些参数。我在使用ObservableCollection作为从属属性时遇到了困难

显示困难的示例是一个包含两个DependencyProperty的主窗口的项目:

  • 一个表示字符串(名为“数据”)的
  • 另一个代表可观测集合(命名为“原点”) 和一个UserControl(名为UserControl1)公开两个类似的DependencyProperty(名为resp.“Liste”和“Noun”)

    主窗口包含文本绑定到“数据”的文本块和ItemsSource绑定到“源”的组合框。两者都很好。 这两个控件都被分解到UserControl1中,DependencyProperty“Liste”和“Non”作为中间变量,UserControl1在MainWindow中使用

    每个DataContext(MainWindow和UserControl1的)都设置为“this”

    问题在于,当分解文本块(在UserControl1中)工作并显示“数据”的内容时,分解组合框不工作,其下拉列表为空

    MainWindow.xaml的代码为:

    <Window x:Class="ChainedBindingUserControl.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"
        xmlns:Local="clr-namespace:ChainedBindingUserControl"
        >
        <StackPanel>
            <TextBlock Text="{Binding Data}"
                       Width="150"
                       />
            <ComboBox ItemsSource="{Binding Origin}"
                       Width="150"
                      />
            <Label Content="--------------------------------------------------"
                   Width="200"
                  />
            <Local:UserControl1 Liste="{Binding Origin}"
                                Noun="{Binding Data}"
                                Height="50" Width="150"
                                />
        </StackPanel>
    </Window>
    
    
    
    其背后的代码是:

    namespace ChainedBindingUserControl
    {
        public partial class MainWindow : Window
        {
            public ObservableCollection<String> Origin
            {
                get { return (ObservableCollection<String>)GetValue(OriginProperty); }
                set { SetValue(OriginProperty, value); }
            }
            public static readonly DependencyProperty OriginProperty =
                DependencyProperty.Register("Origin", typeof(ObservableCollection<String>), typeof(MainWindow),
                        new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender));
    
            public String Data
            {
                get { return (String)GetValue(DataProperty); }
                set { SetValue(DataProperty, value); }
            }
            public static readonly DependencyProperty DataProperty =
                DependencyProperty.Register("Data", typeof(String), typeof(UserControl1),
                        new FrameworkPropertyMetadata("Blablabla", FrameworkPropertyMetadataOptions.AffectsRender));
    
    
    
            public MainWindow()
            {
                InitializeComponent();
                this.DataContext = this;
    
                ObservableCollection<String> zog = new ObservableCollection<String>();
                zog.Add("A");
                zog.Add("B");
                zog.Add("C");
    
                Origin = zog;
            }
        }
    }
    
    namespace ChainedBindingUserControl
    {
        public partial class UserControl1 : UserControl
        {
            public ObservableCollection<String> Liste
            {
                get { return (ObservableCollection<String>)GetValue(ListeProperty); }
                set { SetValue(ListeProperty, value); }
            }
            public static readonly DependencyProperty ListeProperty =
                DependencyProperty.Register("Liste", typeof(ObservableCollection<String>), typeof(UserControl1),
                        new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender));
    
            public String Noun
            {
                get { return (String)GetValue(NounProperty); }
                set { SetValue(NounProperty, value); }
            }
            public static readonly DependencyProperty NounProperty =
                DependencyProperty.Register("Noun", typeof(String), typeof(UserControl1),
                        new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.AffectsRender));
    
    
            public UserControl1()
            {
                InitializeComponent();
                this.DataContext = this;
            }
        }
    }
    
    namespace-ChainedBindingUserControl
    {
    公共部分类主窗口:窗口
    {
    公共可观测采集源
    {
    获取{return(observateCollection)GetValue(OriginProperty);}
    set{SetValue(OriginProperty,value);}
    }
    公共静态只读DependencyProperty OriginProperty=
    DependencyProperty.Register(“原点”、typeof(ObservableCollection)、typeof(主窗口),
    新的FrameworkPropertyMetadata(null,FrameworkPropertyMetadata选项.AffectsRender));
    公共字符串数据
    {
    获取{return(String)GetValue(DataProperty);}
    set{SetValue(DataProperty,value);}
    }
    公共静态只读DependencyProperty DataProperty=
    DependencyProperty.Register(“数据”、typeof(字符串)、typeof(UserControl1),
    新的FrameworkPropertyMetadata(“blabla”,FrameworkPropertyMetadataOptions.AffectsRender));
    公共主窗口()
    {
    初始化组件();
    this.DataContext=this;
    ObservableCollection zog=新的ObservableCollection();
    zog.添加(“A”);
    zog.添加(“B”);
    zog.添加(“C”);
    原点=zog;
    }
    }
    }
    
    UserControl1.xaml文件是:

    <UserControl x:Class="ChainedBindingUserControl.UserControl1"
                 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"
                 Name="root"
                 d:DesignHeight="300" d:DesignWidth="300">
        <StackPanel>
            <TextBlock Text="{Binding Noun}"
                       />
            <ComboBox ItemsSource="{Binding Liste}"
                      />
        </StackPanel>
    </UserControl>
    
    
    
    其背后的代码是:

    namespace ChainedBindingUserControl
    {
        public partial class MainWindow : Window
        {
            public ObservableCollection<String> Origin
            {
                get { return (ObservableCollection<String>)GetValue(OriginProperty); }
                set { SetValue(OriginProperty, value); }
            }
            public static readonly DependencyProperty OriginProperty =
                DependencyProperty.Register("Origin", typeof(ObservableCollection<String>), typeof(MainWindow),
                        new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender));
    
            public String Data
            {
                get { return (String)GetValue(DataProperty); }
                set { SetValue(DataProperty, value); }
            }
            public static readonly DependencyProperty DataProperty =
                DependencyProperty.Register("Data", typeof(String), typeof(UserControl1),
                        new FrameworkPropertyMetadata("Blablabla", FrameworkPropertyMetadataOptions.AffectsRender));
    
    
    
            public MainWindow()
            {
                InitializeComponent();
                this.DataContext = this;
    
                ObservableCollection<String> zog = new ObservableCollection<String>();
                zog.Add("A");
                zog.Add("B");
                zog.Add("C");
    
                Origin = zog;
            }
        }
    }
    
    namespace ChainedBindingUserControl
    {
        public partial class UserControl1 : UserControl
        {
            public ObservableCollection<String> Liste
            {
                get { return (ObservableCollection<String>)GetValue(ListeProperty); }
                set { SetValue(ListeProperty, value); }
            }
            public static readonly DependencyProperty ListeProperty =
                DependencyProperty.Register("Liste", typeof(ObservableCollection<String>), typeof(UserControl1),
                        new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender));
    
            public String Noun
            {
                get { return (String)GetValue(NounProperty); }
                set { SetValue(NounProperty, value); }
            }
            public static readonly DependencyProperty NounProperty =
                DependencyProperty.Register("Noun", typeof(String), typeof(UserControl1),
                        new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.AffectsRender));
    
    
            public UserControl1()
            {
                InitializeComponent();
                this.DataContext = this;
            }
        }
    }
    
    namespace-ChainedBindingUserControl
    {
    公共部分类UserControl1:UserControl
    {
    公共可观测收集列表
    {
    get{return(ObservableCollection)GetValue(ListProperty);}
    set{SetValue(listproperty,value);}
    }
    公共静态只读DependencyProperty ListProperty=
    DependencyProperty.Register(“Liste”、typeof(ObservableCollection)、typeof(UserControl1),
    新的FrameworkPropertyMetadata(null,FrameworkPropertyMetadata选项.AffectsRender));
    公共字符串名词
    {
    获取{return(String)GetValue(NounProperty);}
    set{SetValue(名词属性,值);}
    }
    公共静态只读DependencyProperty属性=
    DependencyProperty.Register(“名词”、typeof(字符串)、typeof(UserControl1),
    新的FrameworkPropertyMetadata(“,FrameworkPropertyMetadataOptions.AffectsRender”);
    公共用户控制1()
    {
    初始化组件();
    this.DataContext=this;
    }
    }
    }
    
    `

    编辑

    根据上提供的信息片段和代码片段,我将UserControl1的代码更改为

        public partial class UserControl1 : UserControl
        {
            public IList Liste
            {
                get { return (List<String>)GetValue(ListeProperty); }
                set { SetValue(ListeProperty, value); }
            }
            public static readonly DependencyProperty ListeProperty =
                DependencyProperty.Register("Liste", typeof(IList), typeof(UserControl1),
                        new FrameworkPropertyMetadata(new List<String>(), FrameworkPropertyMetadataOptions.AffectsRender));
    
            public String Noun
            {
                get { return (String)GetValue(NounProperty); }
                set { SetValue(NounProperty, value); }
            }
            public static readonly DependencyProperty NounProperty =
                DependencyProperty.Register("Noun", typeof(String), typeof(UserControl1),
                        new FrameworkPropertyMetadata("", FrameworkPropertyMetadataOptions.AffectsRender));
    
    
            public UserControl1()
            {
                InitializeComponent();
                this.DataContext = this;
                SetValue(ListeProperty, new List<String>());
            }
        }
    
    公共部分类UserControl1:UserControl
    {
    公共图书馆列表
    {
    获取{return(List)GetValue(listproperty);}
    set{SetValue(listproperty,value);}
    }
    公共静态只读DependencyProperty ListProperty=
    DependencyProperty.Register(“Liste”、typeof(IList)、typeof(UserControl1),
    新建FrameworkPropertyMetadata(新建列表(),FrameworkPropertyMetadata选项.AffectsRender));
    公共字符串名词
    {
    获取{return(String)GetValue(NounProperty);}
    set{SetValue(名词属性,值);}
    }
    公共静态只读DependencyProperty属性=
    DependencyProperty.Register(“名词”、typeof(字符串)、typeof(UserControl1),
    新的FrameworkPropertyMetadata(“,FrameworkPropertyMetadataOptions.AffectsRender”);
    公共用户控制1()
    {
    初始化组件();
    this.DataContext=this;
    SetValue(ListProperty,new List());
    }
    }
    
    但它仍然不起作用

    问题不是来自DataContext,因为TextBlock按预期工作

    这里的问题很具体:为什么当属性的类型为String时,充当绑定中间层的DependecProperty起作用,而当属性的类型为ObservableCollection(或List等)时,DependecProperty不起作用


    提前感谢您的解释。

    假设您正在创建具有接受集合的属性的控件:

     public class CustomControl : Control
     { 
     public IEnumerable<string> Items { get; set; } 
     }
    
    公共类CustomControl:控件
    { 
    公共IEnumerable项{get;set;}
    }
    
    如果希望属性项充当绑定目标,则必须将其更改为依赖项属性:

    public class CustomControl : Control
    {
     public static readonly DependencyProperty ItemsProperty = 
                 DependencyProperty.Register("Items", typeof(IEnumerable<string>), typeof (CustomControl), new PropertyMetadata(new List<string>())); 
    
         public IEnumerable<string> Items 
         { 
             get { return (IEnumerable<string>) GetValue(ItemsProperty); } 
             set { SetValue(ItemsProperty, value); } 
         } 
    }
    
    公共类CustomControl:控件
    {
    公共静态只读从属属性ItemsProperty=
    DependencyProperty.Register(“项”)、typeof(IEnumerable)、typeof(CustomControl)、new PropertyMetada
    
    <Grid>
       <DependencyPropertiesCollection:CustomControl> 
           <DependencyPropertiesCollection:CustomControl.Items> 
              <System:String>Item 1</System:String> 
              <System:String>Item 2</System:String> 
              <System:String>Item 3</System:String> 
              <System:String>Item 4</System:String> 
              <System:String>Item 5</System:String>
           </DependencyPropertiesCollection:CustomControl.Items>
      </DependencyPropertiesCollection:CustomControl> 
     </Grid>
    
    public class CustomControl : Control  
    { 
          public static readonly DependencyProperty ItemsProperty = DependencyProperty.Register("Items", typeof (IList), typeof (CustomControl), new PropertyMetadata(new List<string>())); 
    
      public IList Items 
      { 
           get { return (IList)GetValue(ItemsProperty); } 
           set { SetValue(ItemsProperty, value); }
      } 
    
      public CustomControl() 
      {
            Items = new List<string>(); 
      } 
     }
    
    <TextBlock Text="{Binding Noun}"
               />
    <ComboBox ItemsSource="{Binding Liste}"
              />
    
    <TextBlock Text="{Binding ElementName=root, Path=Noun}"
               />
    <ComboBox ItemsSource="{Binding ElementName=root, Path=Liste}"
              />