Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 当datacontext是列表时,为什么我的文本框没有正确初始化?_C#_Wpf - Fatal编程技术网

C# 当datacontext是列表时,为什么我的文本框没有正确初始化?

C# 当datacontext是列表时,为什么我的文本框没有正确初始化?,c#,wpf,C#,Wpf,我有一个英雄班。它只有一个属性名,并且实现了关于更改的接口 public class Hero : INotifyPropertyChanged, INotifyCollectionChanged { public string Name { get { return _name; } set { _name = value; if (PropertyChanged != null)

我有一个英雄班。它只有一个属性名,并且实现了关于更改的接口

public class Hero : INotifyPropertyChanged, INotifyCollectionChanged
 {
     public string Name { get { return _name; } 
         set
         {
             _name = value;
             if (PropertyChanged != null)
             {
                 PropertyChanged(this, new PropertyChangedEventArgs("Name"));
             }
             if (CollectionChanged != null)
             {
                 CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace));
             }
         }
     }
    private string _name = "";
}
我的xaml如下。我将文本的datacontext绑定到在后台代码中定义的名为Heros的集合

<Window x:Class="Chap21_2.TestCollection"
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     Title="TestCollection" Height="640" Width="480"
     DataContext="{Binding RelativeSource={RelativeSource Self}}">
  <Grid>
       <Grid.RowDefinitions>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
       </Grid.RowDefinitions>
       <TextBox Grid.Row="1" Text="{Binding Name}" DataContext="{Binding Heros}"></TextBox>
       <Button Grid.Row="2" Content="aa" ></Button>
  </Grid>
 </Window>

这是我的密码。它初始化集合,问题是当Init()顺序改变时,结果会不同

public partial class TestCollection : Window
 {
     public ObservableCollection<Hero> Heros { get { return _heros; } set { _heros = value; } }

    private ObservableCollection<Hero> _heros = new ObservableCollection<Hero>();


     public TestCollection()
     {
         // If move Init() here, it'll works.
         InitializeComponent();
         Init();   
     }

    void Init()
     {
         Hero hero = new Hero("Bu Lv", 100, 88, 100, 30);

        _heros.Add(hero);
         hero.HP = 88;

        hero = new Hero("Fei Zhang", 100, 88, 100, 30);
         hero.HP = 90;
         _heros.Add(hero);
     }
 }
公共部分类TestCollection:窗口
{
公共ObservableCollection Heros{get{return{U Heros;}set{U Heros=value;}}
私有ObservableCollection_heros=新ObservableCollection();
公共测试集合()
{
//如果将Init()移到这里,它就会工作。
初始化组件();
Init();
}
void Init()
{
英雄=新英雄(“步吕”,100,88,100,30);
_添加(英雄);
hero.HP=88;
英雄=新英雄(“张飞”,100,88,100,30);
hero.HP=90;
_添加(英雄);
}
}
当我启动代码时,文本框并没有显示我期望的“bulv”。 但是如果我在InitializedComponent()之前移动Init(),它就会工作。
为什么?

这可能是由于将集合绑定到单个文本框。如果我将其更改为使用ItemsControl,则Init可以位于InitializeComponent之后。以下是我所做的事情

Hero.cs TestCollection.xaml 这包括您的原稿,并作了一些更改,以便于说明

<Window x:Class="Chap21_2.TestCollection"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     Title="TestCollection" Height="640" Width="480"
     DataContext="{Binding RelativeSource={RelativeSource Self}}">
   <Grid>
      <Grid.RowDefinitions>
         <RowDefinition Height="Auto"></RowDefinition>
         <RowDefinition Height="*"></RowDefinition>
         <RowDefinition Height="Auto"></RowDefinition>
      </Grid.RowDefinitions>
      <!-- Your original binding -->
      <TextBox Grid.Row="0" Text="{Binding Name}" DataContext="{Binding Heros}" />
      <!-- My added ItemsControl for example purposes -->
      <ItemsControl Grid.Row="1" ItemsSource="{Binding Heros}">
         <ItemsControl.ItemTemplate>
            <DataTemplate>
               <TextBox Text="{Binding Name}" />
            </DataTemplate>
         </ItemsControl.ItemTemplate>
      </ItemsControl>

      <Button Grid.Row="2" Content="aa" ></Button>
   </Grid>
</Window>

TestCollection.xaml.cs 您的示例没有包括所有其他属性,因此出于本示例的目的,我将它们注释掉

public partial class TestCollection : Window
{
  public ObservableCollection<Hero> Heros { get { return _heros; } set { _heros = value; } }
  private ObservableCollection<Hero> _heros = new ObservableCollection<Hero>();

  public TestCollection()
  {
     // Putting this here allows the collection to populate BEFORE the UI is initialized.
     // Init(); 
     InitializeComponent();
     // Putting it here is normal. The ItemsControl works, but the single TextBox binding will not.
     Init();
  }

  private void Init()
  {
     Hero hero;
     //Hero hero = new Hero("Bu Lv", 100, 88, 100, 30);
     //hero.HP = 88;
     hero = new Hero();
     hero.Name = "Bu Lv";
     _heros.Add(hero);

     //hero = new Hero("Fei Zhang", 100, 88, 100, 30);
     //hero.HP = 90;
     hero = new Hero();
     hero.Name = "Fei Zhang";
     _heros.Add(hero);
  }
}
公共部分类TestCollection:窗口
{
公共ObservableCollection Heros{get{return{U Heros;}set{U Heros=value;}}
私有ObservableCollection_heros=新ObservableCollection();
公共测试集合()
{
//将其放在此处允许在初始化UI之前填充集合。
//Init();
初始化组件();
//把它放在这里是正常的。ItemsControl可以工作,但是单个文本框绑定不能。
Init();
}
私有void Init()
{
英雄;
//英雄=新英雄(“步吕”,100,88,100,30);
//hero.HP=88;
英雄=新英雄();
hero.Name=“Bu-Lv”;
_添加(英雄);
//英雄=新英雄(“张飞”,100,88,100,30);
//hero.HP=90;
英雄=新英雄();
hero.Name=“张飞”;
_添加(英雄);
}
}
我的建议是,如果要显示集合中的单个模型,可以添加“SelectedHero”或仅包含单个Hero实例的类似属性。绑定到某个对象的集合通常用于呈现集合中的所有实例


无论从哪种角度看,您都可以将Init()放在initializeComponent()之前或之后,因为您没有直接与UI交互。

对于初学者来说,您不需要在只有string属性的类上实现collection changed。我也不清楚为什么要在xaml中将datacontext设置为自绑定,简单地设置datacontext=this会更容易;在初始化组件后的代码隐藏中,如果这是您想要的,请Hanks Chris。绑定到组合框怎么样?我发现如果我将Init()放在InitializeComponent()之前,组合框将自动选择第一条记录。但是如果我将Init()放在InitializeComponent()之后,它将不会选择任何记录。xaml代码如下所示:。有什么建议吗?@System我不知道为什么它没有通知我你的评论,但我在浏览我的列表时看到了。当
Init()
InitializeComponent()
之后时,它不选择任何内容的原因是该控件是使用空集合初始化的。在我的表单中,有一个主视图模型,它具有表单的所有从属属性。这包括各种可观察到的集合。
SelectedIndex
将绑定到其中一个属性。然后,这只是在填充之后初始化索引的问题。由于没有这样的绑定,您需要直接访问它。如果将
Init()
放在后面,则可以通过编程方式选择它。在组合框中添加一个名称,如
,然后您可以这样选择它:
cboHeroes.SelectedIndex=0。或者,为窗体创建一个主视图模型,并使用DependencyProperties单向或双向绑定。请记住我关于“不直接与UI交互”的说明。如果要在
SelectedIndex
更改后执行代码,则必须在
InitializeComponent()之后执行。它还假设集合中有内容。谢谢你,克里斯。我得到了它。
public partial class TestCollection : Window
{
  public ObservableCollection<Hero> Heros { get { return _heros; } set { _heros = value; } }
  private ObservableCollection<Hero> _heros = new ObservableCollection<Hero>();

  public TestCollection()
  {
     // Putting this here allows the collection to populate BEFORE the UI is initialized.
     // Init(); 
     InitializeComponent();
     // Putting it here is normal. The ItemsControl works, but the single TextBox binding will not.
     Init();
  }

  private void Init()
  {
     Hero hero;
     //Hero hero = new Hero("Bu Lv", 100, 88, 100, 30);
     //hero.HP = 88;
     hero = new Hero();
     hero.Name = "Bu Lv";
     _heros.Add(hero);

     //hero = new Hero("Fei Zhang", 100, 88, 100, 30);
     //hero.HP = 90;
     hero = new Hero();
     hero.Name = "Fei Zhang";
     _heros.Add(hero);
  }
}