WinRT根据ListViewItem的兄弟

时间:2015-12-22 19:38:25

标签: winrt-xaml listviewitem

我正在使用ListView并将ItemsSources设置为Message对象的ObservableCollection。 ListViewItem的DataTemplate包含一个自定义控件。我在自定义控件上定义了一个Message属性,并将此自定义控件上的Message属性绑定到ListViewItem的dataContext。当在自定义控件上触发加载的事件时,我想将其Message上的ReceivedDate集与此ListViewItem的兄弟上设置的ReceivedDate进行比较。由于在Loaded事件被触发时在某些ListViewItem上设置了Message属性而没有在某些事件上设置,因此这种方法不能始终如一地工作。

示例:

<local:ListView x:Name="MyMessagesView"
                              Visibility="Collapsed"
                              ItemsSource="{Binding Messages}"
                              ItemContainerStyle="{StaticResource AppListViewItemStyle}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <dm:MyScreenRow Message="{Binding}"/>
            </DataTemplate>
        </ListView.ItemTemplate>
    </local:ListView>

在我的CustomControl背后的代码中,我处理Loaded事件。我想比较当前ListViewItem上的ReceivedTime属性和它以前的兄弟,并在ListViewItem中显示一个子元素。 Loaded事件不是处理这个问题的正确位置吗?如果没有,有关如何处理这个的任何建议吗?

    public MyScreenRow()
    {
        this.InitializeComponent();
        this.Loaded += MyScreenRow_Loaded;
    }

    private static void MyScreenRow_Loaded(object sender, RoutedEventArgs e)
    {
        MyScreenRow screenRow = sender as MyScreenRow;

        if (screenRow.Message == null)
        {
            return;
        }

        ListViewItemPresenter presenter = (ListViewItemPresenter)VisualTreeHelper.GetParent(screenRow);

        if (presenter != null)
        {
            ListViewItem currentViewItem = (ListViewItem)VisualTreeHelper.GetParent(presenter);

            if (currentViewItem != null)
           {
                ListView listView = (ListView)ItemsControl.ItemsControlFromItemContainer(currentViewItem);

                if (listView != null)
                {
                    int indexOfCurrentContainer = listView.IndexFromContainer(currentViewItem);

                    if (indexOfCurrentContainer == 0)
                    {
                        screenRow.GroupHeader.Visibility = Visibility.Visible;
                    }
                    else
                    {
                        // Get the previous container info
                        ListViewItem previousViewItem = (ListViewItem)listView.ContainerFromIndex(indexOfCurrentContainer - 1);

                        if (previousViewItem != null)
                        {
                            MyScreenRow previousScreenRow = (MyScreenRow)previousViewItem.ContentTemplateRoot;

                            if (previousScreenRow != null
                                && previousScreenRow.Message != null
                                && previousScreenRow.Message.ReceivedTimeUtc != null)
                            {
                                if (screenRow.Message != null
                                    && screenRow.Message.ReceivedTimeUtc != null)
                                {
                                    if (previousScreenRow.Message.ReceivedTimeUtc.Date.CompareTo(screenRow.Message.ReceivedTimeUtc.Date) != 0)
                                    {
                                        screenRow.GroupHeader.Visibility = Visibility.Visible;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }        

}

1 个答案:

答案 0 :(得分:0)

是..因为您猜测在加载的事件中执行此操作将无法工作,因为加载的事件仅被触发一旦listview首次实例化并加载了一些元素后,它就不会被触发。

我强烈建议您使用LayoutUpdated事件。 这是UIElement的一部分,因此windows宇宙中的每个控件都必须拥有它。

在布局更改时触发..如果列表中添加或删除新项目,则会触发..

现在更有趣的部分..如果您不想一次性完成所有控件,那么您可以使用ContainerContentChanging这将允许您仅对视图中的项目应用更改。

<ListView LayoutUpdated="ListView_LayoutUpdated" ContainerContentChanging="ListView_ContainerContentChanging"/>

快速教程链接:http://blogs.msdn.com/b/hanxia/archive/2013/11/04/incremental-update-item-data-for-listviewbased-controls-in-windows-8-1.aspx