为什么不是';这个数据绑定不起作用
本文关键字:数据绑定 不起作用 为什么不 | 更新日期: 2023-09-27 18:29:01
所以我对WPF数据绑定是全新的,它很复杂。在这一点上,我试图创建一个预制测试项目的列表,并在按下按钮时将其显示在带有数据模板的列表框中。经过几个小时对教程和MSDN的困惑,这是我能想到的最好的。
我想列出的数据项来自:
class ListingItem
{
private string title;
private string user;
private string category;
//Dummy constructor for test purposes
public ListingItem()
{
title = "TestTitle";
user = "TestUser";
category = "TestCatagory";
}
}
快速而肮脏的列表创建者:
class ListMaker
{
public static List<ListingItem> getListing()
{
List<ListingItem> listing = new List<ListingItem>();
for(int i = 0; i <100; i++)
{
listing.Add(new ListingItem());
}
return listing;
}
}
列表本身的XAML:
<ListBox x:Name="Listing">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<TextBlock Foreground="Gray" Margin="25,0,0,0" Text="{Binding user}"/>
<TextBlock Foreground="Gray" Margin="25,0,0,0" Text="{Binding category}"/>
</StackPanel>
<TextBlock Foreground="Black" Width="270" TextWrapping="Wrap" Text="{Binding title}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
最后,按钮点击事件,本应使魔术发生:
private void TabClickEvent(object sender, RoutedEventArgs e)
{
Listing.DataContext = RedditScanner.getListing();
}
问题是,很明显,魔法并没有发生。没有错误或任何简单的事情,我只是按下按钮,看不到列表框有任何变化。有什么帮助吗?
您不能绑定到私有字段。我想,甚至连公共领域都没有。
使用属性:
class ListingItem
{
//private string title;
//private string user;
//private string category;
public string Title { get; set; }
public string User { get; set; }
public string Category { get; set; }
//Dummy constructor for test purposes
public ListingItem()
{
Title = "TestTitle";
User = "TestUser";
Category = "TestCatagory";
}
}
对于完全数据绑定,您必须在ListingItem
上实现INotifyPropertyChanged
。
魔法没有发生。没有错误或任何如此简单的事情,
在执行过程中,请密切关注"输出窗口"。报告了绑定错误。
对您的代码进行了一些小的更改,如下所述。
class ListingItem
{
public string title { get; set; }
public string user { get; set; }
public string category { get; set; }
//Dummy constructor for test purposes
public ListingItem()
{
title = "TestTitle";
user = "TestUser";
category = "TestCatagory";
}
}
- 在列表项类中,我将标题、用户和类别更改为属性(get;set;)。我还需要将它们公开,以便可以通过绑定访问它们
class ListMaker
{
public static List getListing()
{
List listing = new List();
for (int i = 0; i < 100; i++)
{
listing.Add(new ListingItem());
}
return listing;
}
}
- ListMaker类没有更改
public class CommandHandler : ICommand
{
private Action _action;
private bool _canExecute;
public CommandHandler(Action action, bool canExecute=true)
{
_action = action;
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return _canExecute;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
_action();
}
}
- 我引入了一个能够绑定按钮的新类。这种类如果比较常见
<Window x:Class="SimpleDatabinding.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:viewmodel="clr-namespace:SimpleDatabinding"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<viewmodel:MainWindowViewModel/>
</Window.DataContext>
<Grid>
<DockPanel>
<Button Command="{Binding FillListCommand}" DockPanel.Dock="Top">Fill List</Button>
<ListBox ItemsSource="{Binding Listing}" DockPanel.Dock="Top">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<TextBlock Foreground="Gray" Margin="25,0,0,0" Text="{Binding user}"/>
<TextBlock Foreground="Gray" Margin="25,0,0,0" Text="{Binding category}"/>
</StackPanel>
<TextBlock Foreground="Black" Width="270" TextWrapping="Wrap" Text="{Binding title}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DockPanel>
</Grid>
</Window>
- 注意添加了xmlns:viewmodel="clr-namespace:SimpleDatabinding"。SimpleDatabinding是项目的名称。它用于在下面的数据上下文中定位视图模型
- Window.DataContext将WPF页面绑定到视图模型。我调用了我的类MainWindowViewModel(请参见下文)。这将自动创建视图模型的实例并将其绑定到窗口
- 我引入了一个点击按钮。它绑定到一个命令FillListCommand。我将在下面的视图模型中对此进行定义
- 我更新了ListBox上的ItemsSource,使其绑定到Listing属性
- 除此之外,我觉得还是一样的
class MainWindowViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public List Listing { get; set; }
public CommandHandler FillListCommand { get; set; }
public MainWindowViewModel()
{
FillListCommand = new CommandHandler(DoFillList);
}
public void DoFillList()
{
Listing = ListMaker.getListing();
ProperyHasChanged("Listing");
}
private void ProperyHasChanged(string propertyName)
{
if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
- 最后,在viewmodel类中,我实现了INotifyPropertyChanged接口。这是一种通知UI视图模型上的值已更改的机制。在大多数实现中,它被封装在某种ViewModel基类中,但我把它留在了中,以便您可以看到它
- 如上所述,我将Listing变量转换为公共属性(get;set;),以便可以通过绑定访问它
- 我创建了一个名为FillListCommand的CommandHandler属性。这使用了上面的类。按钮绑定到此变量。视图模型的构造函数初始化并指向单击按钮时要调用的函数
- 最后,在DoFillList函数中,我初始化了Listing,但我也使用通知让UI知道它已经更改
很抱歉写了这么多。希望这能有所帮助。我认为这和你以前的没有太大的不同。
不要忘记用适当的标记来装饰您的数据成员和服务方法。
这些短视频非常适合学习WCF:http://channel9.msdn.com/Shows/Endpoint?sort=rating#tab_sortBy_rating
我发现我的代码只有两个问题:
-
属性在ListingItem中设置为私有,HenkHolterman捕获(+1ed)
-
我没有在列表中的任何位置设置ItemSource。
我根本不需要做彼得·特伦里提到的任何其他事情。