2016-05-10 6 views
1

Я все еще пытаюсь раздобыть привязку данных в WPF, и поэтому у меня возникла проблема с тем, как решить эту проблему за последние 10 часов:C# WPF DataBinding «Не удается найти свойство»

У меня есть объект с именем birdList, который состоит из списка объектов Bird (bird1 и bird2). Я сделал все свойства внутри объектов общедоступными. Когда я пытаюсь передать данные, связываю свойство Common_Name с TextBlock, я ничего не получаю. Глядя на выходе в Visual Studio, я вижу следующие ошибки/предупреждения:

System.Windows.Data Warning: 60 : BindingExpression (hash=47755470): Default mode resolved to OneWay 
System.Windows.Data Warning: 78 : BindingExpression (hash=47755470): Activate with root item 'birdList' 
System.Windows.Data Warning: 108 : BindingExpression (hash=47755470): At level 0 - for String.Bird found accessor <null> 
System.Windows.Data Warning: 108 : BindingExpression (hash=47755470): At level 0 - for EnumerableCollectionView.Bird found accessor <null> 
System.Windows.Data Warning: 108 : BindingExpression (hash=47755470): At level 0 - for Char.Bird found accessor <null> 

System.Windows.Data Error: 40 : BindingExpression path error: 'Bird' property not found on 'object' ''String' (HashCode=-874795121)'. 

System.Windows.Data Warning: 103 : BindingExpression (hash=47755470): Replace item at level 1 with {NullDataItem} 
System.Windows.Data Warning: 88 : BindingExpression (hash=47755470): TransferValue - using fallback/default value '' 
System.Windows.Data Warning: 89 : BindingExpression (hash=47755470): TransferValue - using final value '' 

C# Код:

public Birds birdList { get; set; } 

    Bird bird1 { get; set; } 
    Bird bird2 { get; set; } 

public MainWindow() 
    { 

     InitializeComponent(); 

     birdList = new Birds(); 

     bird1 = new Bird(); 
     bird2 = new Bird(); 

     bird1.Common_Name = "Mallard"; 
     bird2.Common_Name = "Red-winged Blackbird"; 

     birdList.Bird.Add(bird1); 
     birdList.Bird.Add(bird2); 

     birdList.Test = "Testing!"; 

     this.DataContext = this; 

     this.Photos = (PhotoCollection)(Application.Current.FindResource("Photos") as ObjectDataProvider).Data; 
     this.Photos.Path = "E:\\Network Drive\\SarDonnie's Documents - Networked\\Birds\\Ducks, Geese, and Swans (Anatidae)\\Mallard\\Clear Lake Bay Park 1-18-16"; 

    } 

public class Birds 
{ 
    public string Test { get; set; } 

    public List<Bird> _Birds = new List<Bird>(); 
    public List<Bird> Bird 
    { 
     get 
     { 
      return this._Birds; 
     } 
    } 
} 

public class Bird 
{ 

    public string Common_Name { get; set; } 

} 

XMAL:

 <Grid Grid.Column="2"> 
      <ContentControl Content="birdList"> 
       <ContentControl.ContentTemplate> 
        <DataTemplate> 
         <StackPanel> 
          <TextBlock Height="50" Text="{Binding Bird.Common_Name,diag:PresentationTraceSources.TraceLevel=High}"> 
          </TextBlock> 
         </StackPanel> 
        </DataTemplate> 
       </ContentControl.ContentTemplate> 
      </ContentControl> 
     </Grid> 

Я также попытался это проверить, обращающийся к Испытательное свойство внутри birdList Объект:

<Grid Grid.Column="2"> 
      <ContentControl Content="birdList"> 
       <ContentControl.ContentTemplate> 
        <DataTemplate> 
         <StackPanel> 
          <TextBlock Height="50" Text="{Binding Test> 
          </TextBlock> 
         </StackPanel> 
        </DataTemplate> 
       </ContentControl.ContentTemplate> 
      </ContentControl> 
     </Grid> 

Мой вопрос: почему я не могу найти свойство birdList.Bird.Common_Name или свойство birdList.Test?

Спасибо!

Также не стесняйтесь указать мне некоторые хорошие сайты, на которых размещена информация о WPF. Я ненавижу ударить головой по этой клавиатуре и не получить нигде!

ответ

3

Ваш код имеет две проблемы:

  1. Вы должны указать путь к «списку» в XAML (через свойство «ItemsSource»).
  2. Используйте элементы управления, которые принимают коллекции, такие как ListBox.

Вот мой код:

  • MainWindow.xaml.cs
public partial class MainWindow : Window 
{ 
    public List<Bird> Birds { get; set; } 

    public MainWindow() 
    { 
     InitializeComponent(); 

     Birds = new List<Bird>(); 

     var bird1 = new Bird(); 
     bird1.CommonName = "Mallard"; 
     Birds.Add(bird1); 

     var bird2 = new Bird(); 
     bird2.CommonName = "Red-winged Blackbird"; 
     Birds.Add(bird2); 

     this.DataContext = this; 
    } 

    public class Bird 
    { 
     public string CommonName { get; set; } 
    } 
} 
  • MainWindow.xaml
<Grid> 
    <ListBox ItemsSource="{Binding Birds}" DisplayMemberPath="CommonName" /> 
</Grid> 

EDIT

Если вам необходимо обновить код во время выполнения, следуйте советам Jai. Я только показал минимальное решение вопроса.

EDIT2

Всегда помните, чтобы использовать свойства в связывании, или иначе это не будет работать.

public class Birds 
{ 
    public string Test { get; set; } 

    //Binding source must be a property!! 
    public List<Bird> _Birds { get; set; } = new List<Bird>(); 
    public List<Bird> Bird 
    { 
     get 
     { 
      return this._Birds; 
     } 
    } 
} 
<Grid> 
    <DataGrid ItemsSource="{Binding birdList._Birds}" /> 
</Grid> 
+0

Большое спасибо за ответ! – user3732456

+0

Большое спасибо за ответ! Реализация вашего кода работает, однако, я действительно озадачен тем, как одна форма моего кода не работает. Как я уже сказал, я работал над ним в течение 10 часов. Итак, в какой-то момент я использовал DataGrid с ItemSource = "{Bindng birdList._Birds}". birdList._Birds - список птиц, но он не будет отображаться! Это будет эквивалентно вашему коду, но по какой-то причине это не так. Единственное, о чем я могу думать, это мой синтаксис. Как я могу получить доступ к списку birdList._Birds? – user3732456

+0

Вы связали свойство, которое хотите отобразить в DataGrid? – Doncot

1

Хорошо, есть совсем немного проблемы там.

Во-первых, у вас есть список птиц, но у вас есть только один TextBlock, чтобы отобразить его. Если вы вручную сделали несколько TextBlock (которые вы нам не показали), то нет смысла составлять список птиц, потому что это означает, что ваш взгляд точно знает, сколько птиц там (в вашей модели просмотра ???). Поэтому Doncot имеет право сказать, что вы должны использовать ListBox или любые другие элементы управления, которые позволяют отображать список элементов.

Во-вторых, если вы хотите использовать ListBox (или что-то подобное), вам нужно будет рассмотреть список птиц. Связывание всегда связано с INotifyPropetyChanged, INotifyCollectionChanged и DependencyProperty. Создание класса просто для хранения списка не представляется необходимым, если у вас нет других специальных требований, о которых мы не знаем.

Doncot совсем рядом, но я хочу коснуться немного больше. Использование List<Bird> прекрасно работает, за исключением того, что ваш ListBox не будет знать, что ему необходимо обновить себя, когда список будет изменен позже. Это связано с тем, что List<Bird> не уведомляет механизм привязки при изменении.

Если вы реализуете это вместе с INotifyPropertyChanged, ваше связывание будет иметь возможность запускать, когда весь List<Bird> будет повторно создан (т. Е. Birds = new List<Bird>();). Обычно это не то, что вы хотите.

Если вы меняете целое List<Bird> на ObservableCollection<Bird>, ваше привязку срабатывает, когда вы делаете Birds.Add(new Bird());. Это связано с тем, что ObservableCollection<> - это реализация интерфейса INotifyCollectionChanged, который вы также можете реализовать самостоятельно. До этого момента ваша привязка довольно солидная, за исключением того, что она не знает, когда изменяется Bird внутри этого списка.

Рассмотрим это:

Birds.ElementAt(0).Common_Name = "New Bird Name!"; 

Сама коллекция не изменяется, потому что он все еще держится на обращение того же Bird экземпляра. Поэтому механизм привязки не будет знать об этом изменении. Чтобы решить эту проблему, ваш класс Bird должен также реализовать INotifyPropertyChanged, что похоже на то, что ответил vishakh369.

+0

Спасибо за дополнительный вход! Это действительно помогло мне понять привязку на более глубоком уровне. BTW: Раньше я использовал DataGrid, но на 200 итераций я пытался использовать случайные вещи, которые я нашел онлайн (иногда я отчаянно). Кроме того, я добавил комментарий выше, дайте мне знать, если вы знаете ответ. Спасибо^_ ^ – user3732456

Смежные вопросы