我仍然试图在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信息的好网站。我讨厌在这个键盘上敲我的头而没有在哪里!
答案 0 :(得分:3)
您的代码有两个问题:
这是我的代码:
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; }
}
}
<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
(或类似的东西),你需要考虑你的鸟类清单。绑定始终与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的回答类似。