C#WPF DataBinding"无法找到属性"

时间:2016-05-10 02:17:03

标签: c# wpf xaml data-binding

我仍然试图在WPF中解决数据绑定问题,因此我在过去10小时内如何解决此问题时遇到了一些问题:

我有一个名为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对象中的Test属性:

<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信息的好网站。我讨厌在这个键盘上敲我的头而没有在哪里!

2 个答案:

答案 0 :(得分:3)

您的代码有两个问题:

  1. 您需要将“list”的路径告诉xaml(通过“ItemsSource”属性)。
  2. 使用接受ListBox等集合的控件。
  3. 这是我的代码:

    • 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>
    

    修改

    如果您需要在运行时更新代码,请遵循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>
    

答案 1 :(得分:1)

好的,那里有很多问题。

首先,您有一个鸟类列表,但您只有一个TextBlock来显示它。如果您手动制作了多个TextBlock(您没有向我们展示),那么就没有必要制作一个鸟类列表,因为这意味着您的视图确切地知道有多少只鸟(在你的viewmodel ???)。因此,Doncot说你应该使用ListBox或任何其他允许你显示项目列表的控件是正确的。

其次,如果你想使用ListBox(或类似的东西),你需要考虑你的鸟类清单。绑定始终与INotifyPropetyChangedINotifyCollectionChangedDependencyProperty相关。除非您有其他我们不了解的特殊要求,否则创建一个类只是为了保存您的列表似乎没有必要。

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的回答类似。