如何将ObservableCollection的前N个项目绑定到ItemsControl?

时间:2019-08-15 12:59:56

标签: c# wpf observablecollection

我想将ObservableCollection的前N个项目绑定到ItemsControl。

我已经尝试过以下解决方案: Binding to first N items in an ObservableCollection on a ListView

这是我的代码:
XAML:

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <ItemsControl x:Name="IC" VirtualizingStackPanel.IsVirtualizing="True" VirtualizingStackPanel.VirtualizationMode="Recycling">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Border BorderBrush="#cecece" BorderThickness="0,0,0,1" Background="Transparent" >
                        <TextBlock Text="{Binding ABC}"></TextBlock>
                    </Border>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <VirtualizingStackPanel></VirtualizingStackPanel>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
        </ItemsControl>
        <Button Grid.Column="1" Click="Button_Click"></Button>
    </Grid>
</Window>

隐藏代码:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApp1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            IC.ItemsSource = CM.TopCollection;
        }
        CollectionModel CM = new CollectionModel();
        public class TestModel {
            public string ABC { get; set; }
        }
        public class CollectionModel : ObservableCollection<TestModel>, INotifyPropertyChanged
        {
            public CollectionModel()
            {
                CollectionChanged += MyCollection_CollectionChanged;
            }          

            private void MyCollection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
            {   // to notify XAML-side binding
                OnPropertyChanged(new PropertyChangedEventArgs(nameof(TopCollection)));
            }
            public IEnumerable<TestModel> TopCollection => this.Take(10);
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            CM.Add(new TestModel() {ABC= Guid.NewGuid().ToString() });
        }
    }
}

我单击了按钮。但是,CM已成功添加新项目,但用户界面未更新任何内容。

为什么是这个?

我使用一个断点进行测试,发现CollectionChangedOnPropertyChanged都可以正常工作。但是为什么UI仍然没有更新?

你能帮我吗?谢谢。

2 个答案:

答案 0 :(得分:1)

您需要绑定到class VAE_CNN(nn.Module): def __init__(self, h, w): super(VAE_CNN, self).__init__() self.h = h self.w = w # Encoder self.conv1 = nn.Conv2d(3, 16, kernel_size=3, stride=1, padding=1, bias=False) self.bn1 = nn.BatchNorm2d(16) self.conv2 = nn.Conv2d(16, 32, kernel_size=3, stride=2, padding=1, bias=False) self.bn2 = nn.BatchNorm2d(32) self.conv3 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1, bias=False) self.bn3 = nn.BatchNorm2d(64) self.conv4 = nn.Conv2d(64, 16, kernel_size=3, stride=1, padding=1, bias=False) self.bn4 = nn.BatchNorm2d(16) # Latent vectors mu and sigma self.fc1 = nn.Linear(h//2 * w//2 * 16, 2048) self.fc_bn1 = nn.BatchNorm1d(2048) self.fc21 = nn.Linear(2048, 2048) self.fc22 = nn.Linear(2048, 2048) # Sampling vector self.fc3 = nn.Linear(2048, 2048) self.fc_bn3 = nn.BatchNorm1d(2048) self.fc4 = nn.Linear(2048, h//2 * w//2 * 16) self.fc_bn4 = nn.BatchNorm1d(h//2 * w//2 * 16) # Decoder self.conv5 = nn.ConvTranspose2d(16, 64, kernel_size=3, stride=1, padding=1, bias=False) self.bn5 = nn.BatchNorm2d(64) self.conv6 = nn.ConvTranspose2d(64, 32, kernel_size=3, stride=1, padding=1, bias=False) self.bn6 = nn.BatchNorm2d(32) self.conv7 = nn.ConvTranspose2d(32, 16, kernel_size=3, stride=2, padding=1, output_padding=1, bias=False) self.bn7 = nn.BatchNorm2d(16) self.conv8 = nn.ConvTranspose2d(16, 3, kernel_size=3, stride=1, padding=1, bias=False) self.relu = nn.ReLU() def encode(self, x): conv1 = self.relu(self.bn1(self.conv1(x))) conv2 = self.relu(self.bn2(self.conv2(conv1))) conv3 = self.relu(self.bn3(self.conv3(conv2))) conv4 = self.relu(self.bn4(self.conv4(conv3))) conv4 = conv4.view(-1, self.h//2 * self.w//2 * 16) fc1 = self.relu(self.fc_bn1(self.fc1(conv4))) r1 = self.fc21(fc1) r2 = self.fc22(fc1) return r1, r2 def reparameterize(self, mu, logvar): if self.training: std = logvar.mul(0.5).exp_() eps = Variable(std.data.new(std.size()).normal_()) return eps.mul(std).add_(mu) else: return mu def decode(self, z): fc3 = self.relu(self.fc_bn3(self.fc3(z))) fc4 = self.relu(self.fc_bn4(self.fc4(fc3))).view(-1, 16, self.h//2, self.w//2) conv5 = self.relu(self.bn5(self.conv5(fc4))) conv6 = self.relu(self.bn6(self.conv6(conv5))) conv7 = self.relu(self.bn7(self.conv7(conv6))) return self.conv8(conv7).view(-1, 3, self.h, self.w) def forward(self, x): mu, logvar = self.encode(x) z = self.reparameterize(mu, logvar) return self.decode(z), mu, logvar class customLoss(nn.Module): def __init__(self): super(customLoss, self).__init__() self.mse_loss = nn.MSELoss(reduction="sum") def forward(self, x_recon, x, mu, logvar): loss_MSE = self.mse_loss(x_recon, x) loss_KLD = -0.5 * torch.sum(1 + logvar - mu.pow(2) - logvar.exp()) return loss_MSE + loss_KLD model = VAE_CNN(254, 254).to(device) 的{​​{1}}属性,以使$(".fc-right").append('<select class="select_month"><option value="">Select Month</option><option value="1">Jan</option><option value="2">Feb</option><option value="3">Mrch</option><option value="4">Aprl</option><option value="5">May</option><option value="6">June</option><option value="7">July</option><option value="8">Aug</option><option value="9">Sep</option><option value="10">Oct</option><option value="11">Nov</option><option value="12">Dec</option></select>'); $(".select_month").on("change", function (event) { $('#calendar_full').fullCalendar('changeView', 'month', this.value); $('#calendar_full').fullCalendar('gotoDate', y + '-' + this.value + '-1'); }); // y assigned as selected year. 事件生效:

TopCollection

如果将CollectionModel设置为实现PropertyChanged的{​​{1}},则可以在XAML标记中执行以下操作:

public MainWindow()
{
    InitializeComponent();
    DataContext = CM;
    IC.SetBinding(ItemsControl.ItemsSourceProperty, new Binding("TopCollection"));
}

答案 1 :(得分:0)

您的CollectionModel是一个ObservableCollection,您做对了。这意味着当添加/删除项目时,它将引发事件(供订户观察并采取行动)。

但是,实际上绑定到的“ TopCollection”只是一个IEnumerable。简而言之,它不会引发完全绑定数据的事件。

您需要公开TopCollection的ObservableCollection。然后,当其基础数据源更改时,甚至仅在其过滤结果更改时,您都可以引发事件。