Không thể can thiệp vào ContentPresenter của item khi mới thêm nó vào ItemsSource của ItemsControl

Như tiêu đề, mình muốn trích xuất và kiểm soát 1 ContentPresenter của 1 phần tử (item) mình mới thêm vào ItemsSource của ItemsControl (nó là 1 phần tử con của ItemsControl, giống như ListBoxItem của ListBox), khi mình chạy đoạn code trên thì xuất hiện NullReferenceException

MainWindow.xaml
<Window x:Class="ProjectM001.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:PresentationOptions="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options" 
        xmlns:local="clr-namespace:ProjectM001"
        xmlns:sys="clr-namespace:System;assembly=mscorlib" 
        mc:Ignorable="d" WindowStartupLocation="CenterScreen"
        Title="MainWindow" Width="760" Height="400">

    <Grid>
        
        <ItemsControl x:Name="AAAA">
        </ItemsControl>
    </Grid>
</Window>
MainWindow.xaml.cs
public partial class MainWindow : Window
    {
        private ObservableCollection<A> ItemsSource = new ObservableCollection<A>() { new A() { Index = 43 } , new A() { Index = 3 } , new A() { Index = 4 } };
        public MainWindow()
        {
            InitializeComponent();
            AAAA.ItemsSource = ItemsSource;
            AAAA.ItemContainerGenerator.ItemsChanged += ItemContainerGenerator_ItemsChanged;
        }

        private void ItemContainerGenerator_ItemsChanged(object sender, System.Windows.Controls.Primitives.ItemsChangedEventArgs e)
        {
            ContentPresenter contentPresenter = AAAA.ItemContainerGenerator.ContainerFromIndex(3) as ContentPresenter;
            MessageBox.Show(AAAA.ItemContainerGenerator.Items.Count + "/" + AAAA.Items.Count);
            MessageBox.Show(contentPresenter.Content.ToString());
        }

}

ItemsSource mặc định có 3 phần tử index từ 0 -> 2
AAAA.ItemContainerGenerator.ContainerFromIndex(3) - Số 3 ở đây được đặt để thử nghiệm
Khi mình thêm 1 phần tử nữa vào collection, nó sẽ có index là 3, và sau khi trên vào thêm 1 phần tử nữa, nó sẽ gọi cái event ItemContainerGenerator_ItemsChanged
Kết quả của MessageBox đầu tiên hiển thị “4/4” (tức là AAAA.ItemContainerGenerator.Items.Count và AAAA.Items.Count đều bằng 4 - hay nói cách khác phần tử đã được thêm vào)
Nhưng đến MessageBox thứ 2 thì xuất hiện lỗi null.
Mình đoán là ItemsSource tuy đã ném ra thông báo cập nhật List nhưng ItemsControl vẫn chưa tiến hành khởi tạo phần tử con mới ContentPresenter.

Mấy pro có biết cách nào để khắc phục không? Mình xin cảm ơn mấy bạn đã dành thời gian để đọc câu hỏi của mình

Hi bạn,
Bạn có thể sửa code 1 chút như sau để tìm ra lỗi:

    var contentPresenter = AAAA.ItemContainerGenerator.ContainerFromIndex(3);         
    //MessageBox.Show(AAAA.ItemContainerGenerator.Items.Count + "/" + AAAA.Items.Count);
    MessageBox.Show(contentPresenter.GetType().ToString());

Type của contentPresenter là gì?
Có cast qua kiểu ContentPresenter được không?

Ngoài ra, mình chưa chỉ thắc mắc ý tưởng can thiệp vào ContentPresenter của ItemControl để làm gì.
Vì thông thường ContentPresenter được sử dụng trong ControlTemplate để hiện thị ContentControl.

kiểu mình chắc chắn nó sẽ trả về contentpresenter vì mình có làm 1 cái khác mình sửa index cần lấy từ 3 thành 0 để kiểm tra kiểu, chắc chắn là ContentPresenter
ContentPresenter nó có thể sử dụng DataTemplate để dựng dữ liệu Content của nó thành cấu trúc con chứa trong nó
Mình muốn làm vậy là vì mình muốn làm mấy cái kiểu kiểu layer ấy, cái này đè lên cái khác nhưng ZIndex lại không lệ thuộc theo thứ tự phần tử (bình thường dù bạn làm thế nào trong cái ItemTemplate thì với ItemsControl
nó sẽ tạo ra các phần tử con cái sau đè lên cái trước)

1 Like

Mình có giải pháp khác đó là mình sẽ dùng Loaded bên trong phần tử con để can thiệp, nhưng mình sợ giải pháp này ko toàn diện vì mình chưa hiểu lắm phương thức hoạt động của ItemsControl

1 Like

Bạn đã thử ItemsPanel và ItemContainerStyle chưa? Việc các item hiện thị như thế nào Wrap, Stack hay Grid cũng do container quyết định nữa.

Mình cũng không biết mục đích cuối cùng của bạn là gì nên chẳng thể góp ý hơn.

1 Like

Mình đã tìm ra hướng khác để giải quyết vấn đề trên mà không cần phải tự làm 1 cái ItemsControl riêng bằng cách sử dụng event Loaded cho 1 cái FrameworkElement con của cái ContentPresenter trên, mà nói chung cũng không liên quan đến câu hỏi lắm nên không đề cập đến. Cảm ơn bạn đã quan tâm đến câu hỏi của mình.

Mong anh @drgnz khóa bài này lại ạ

83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?