为什么这个数据绑定不起作用?

时间:2013-08-23 22:39:27

标签: c# wpf xaml data-binding windows-phone-8

所以我对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();
    }

问题显然是魔法没有发生。没有错误或任何简单的事情,我只需按下该按钮,看不到对列表框的任何更改。对此有何帮助?

4 个答案:

答案 0 :(得分:2)

您无法绑定到私有字段。我认为甚至不到公共领域。

使用属性:

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";
    }
}

对于完整数据绑定,您INotifyPropertyChanged上会to implement ListingItem

  

魔法没有发生。没有错误或任何容易的事情,

执行期间请密切关注输出窗口。报告绑定错误。

答案 1 :(得分:1)

对您的代码进行了一些小的更改,如下所述。


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是项目的名称。它用于在下面的datacontext中定位视图模型。
  • Window.DataContext将WPF页面绑定到视图模型。我打电话给我的班级MainWindowViewModel(见下文)。这将自动创建视图模型的实例并将其绑定到窗口。
  • 我介绍了一个单击按钮。它绑定到命令 FillListCommand 。我将在下面的视图模型中定义它。
  • 我更新了 ListBox 上的 ItemsSource 以绑定到列表属性。
  • 除此之外,我认为它是一样的。



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 函数中,我初始化列表,但我也使用通知让UI知道它已被更改。

抱歉所有的写作。希望这有点帮助。我认为这与你的不一样。

答案 2 :(得分:0)

不要忘记使用适当的标记装饰您的数据成员和服务方法。

这些简短视频非常适合学习WCF: http://channel9.msdn.com/Shows/Endpoint?sort=rating#tab_sortBy_rating

答案 3 :(得分:0)

我的代码只有2个问题,我发现:

  1. 属性在ListingItem中设置为私有,Henk Holterman抓住了(+ 1ed)

  2. 我没有在列表中的任何地方设置ItemSource。

  3. 我根本不需要做Peter Trenery所提到的任何其他内容。