LINQ匿名类型,自定义类,ObservableCollection和WPF - 它是如何挂在一起的?

时间:2012-04-17 22:22:30

标签: c# wpf linq xaml observablecollection

我有一个非常简单的类,我用LINQ查询填充 - 一切运行良好;

public class CatSummary : INotifyPropertyChanged
{
    private string _catName;
    public string CatName
    {
        get { return _catName; }
        set { if (_catName != value) { _catName = value; NotifyPropertyChanged("CatName"); } }
    }

    private decimal _catAmount;
    public decimal CatAmount
    {
        get { return _catAmount; }
        set { if (_catAmount != value) { _catAmount = value; NotifyPropertyChanged("CatAmount"); } }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    // Used to notify Silverlight that a property has changed.
    private void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));

            //MessageBox.Show("NotifyPropertyChanged: " + propertyName);

        }
    }

}

LINQ位;

        var myOC = new ObservableCollection<CatSummary>();


        var initialQuery = BoughtItemDB.BoughtItems
                         .GroupBy(item => item.ItemCategory)
                         .Select(x => new CatSummary
                          { 
                              CatName = x.Key, 
                              CatAmount = x.Sum(amt => amt.ItemAmount)
                          });

        foreach (var item in initialQuery) myOC.Add(item);

我正在尝试将我的WPF控件绑定到下面XAML中的自定义类;

<ListBox x:Name="boughtItemsListBox" ItemsSource="{Binding CatSummary}" Margin="5,27,-35,100" Width="450" Height="371" Grid.ColumnSpan="2" Grid.RowSpan="2">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Grid HorizontalAlignment="Stretch" Width="440">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="150" />
                    <ColumnDefinition Width="Auto" />
                </Grid.ColumnDefinitions>

                <TextBlock Grid.Column="0" Text="{Binding CatName, StringFormat=g}" TextWrapping="Wrap"  FontSize="{StaticResource PhoneFontSizeSmall}" VerticalAlignment="Top"/>
                <TextBlock Grid.Column="1" Text="{Binding CatAmount, StringFormat=\{0:C\}}" Margin="1" FontSize="{StaticResource PhoneFontSizeSmall}" VerticalAlignment="Top"/>
            </Grid>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

这给我以下错误; BindingExpression路径错误:'MyApp.SpendAnalysis + CatSummary'上找不到'CatSummary'属性

根据我读过的内容,我认为我需要将我的类的属性设置为ObservableCollection属性,但这似乎打破了我的LINQ查询。我已经为此尝试了各种各样,我也找不到任何教程来帮助我理解它应该如何工作。很高兴收到任何建议或指示。

2 个答案:

答案 0 :(得分:2)

使用您的XAML绑定时,DataContext的{​​{1}}应该是一个项目,其中包含boughtItemsListBox类型CatSummary的属性(或IEnumerable<CatSummary>或其他ObservableCollection<CatSummary>的实施者,如果您希望能够实时更改构成列表的项目)。我猜这是你出错的地方。

E.g。如果你真的有更像INotifyCollectionChanged的东西,那么它正在寻找boughtItemsListBox.DataContext = myOC;而没有找到任何东西;您需要做的是将XAML更改为myOC.CatSummary或将代码更改为ItemsSource="{Binding}"(并删除XAML中现在无用的boughtItemsListBox.ItemsSource = myOC;设置。)

答案 1 :(得分:1)

假设您有MyOC属性

private ObservableCollection<CatSummary> _myOC = new ObservableCollection<CatSummary>();
public ObservableCollection<CatSummary> MyOC
{
    get { return _myOC ; }
    set { if (_myOC != value) { _myOC = value; NotifyPropertyChanged("MyOC"); } }
}

将您的ListBox绑定到ObservableCollection,然后每个ListBoxItem的{​​{1}}类型为DataContext

CatSummary

在您的LINQ查询代码中

<ListBox x:Name="boughtItemsListBox" ItemsSource="{Binding MyOc}" ...

重新分配MyOC

var initialQuery = BoughtItemDB.BoughtItems
                    .GroupBy(item => item.ItemCategory)
                    .Select(x => new CatSummary
                     { 
                         CatName = x.Key, 
                         CatAmount = x.Sum(amt => amt.ItemAmount)
                     });

或使用现有的MyOC集合。

MyOC = new ObservableCollection<CatSummary>(initialQuery.ToList());