Как исправить Listview, не отображающий (правильно) ObservableCollections, даже если в нем есть данные? - PullRequest
1 голос
/ 12 июня 2019

Я создаю приложение с 3 функциями и боковым меню для навигации по ним.Одной из функций является TabControl с 4 списками, отображающими элементы (в 4 TabItems).

Существует 2 основных проблемы:

¤ Первыйвсего, когда я нажимаю «FEATURE3», он отображает TabControl, но ListViews не отображают , хотя я знаю, что элементы находятся в ObservableCollections.

НО Если я затем нажму «FEATURE2» и снова нажму «FEATURE3», элементы теперь появляются, но только для A, а не для BC D.

ЕслиСначала я нажимаю «FEATURE2», а затем «FEATURE3», который вообще не отображается.

¤ Моя вторая проблема заключается в том, что когда я добавляю элементы в A, нене обновлять в списке.

Вот мой текущий код:

MainWindow.xaml:

<Window x:Class="A.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:A"
        mc:Ignorable="d"
        Title="MainWindow"
        WindowStyle="None"
        WindowStartupLocation="CenterScreen"
        ResizeMode="NoResize">

    <Window.Resources>
        <DataTemplate x:Key="DataTemplate1">
            <Grid Width="100"
                  Height="30">
                <Grid.RowDefinitions>
                    <RowDefinition Height="8*"/>
                    <RowDefinition Height="1*"/>
                </Grid.RowDefinitions>
                <Image Source="{Binding Path=Image}" Grid.Row="0" Stretch="UniformToFill"/>
                <TextBlock Text="{Binding Path=Name}" Grid.Row="2" Foreground="Black"/>
            </Grid>
        </DataTemplate>
    </Window.Resources>

    <Grid>

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="1*" />
            <ColumnDefinition Width="4*" />
        </Grid.ColumnDefinitions>

        <Grid Grid.Column="0"> <!--LEFT MENU-->

            <StackPanel VerticalAlignment="Top" Margin="20,20,20,0">
                <Button Name="FEATURE1Button" Content="FEATURE1" HorizontalContentAlignment="Left" Height="50" FontSize="24" Click="Click"/>
                <Button Name="FEATURE2Button" Content="FEATURE2" HorizontalContentAlignment="Left" Height="50" FontSize="24" Click="Click"/>
                <Button Name="FEATURE3Button" Content="FEATURE3" HorizontalContentAlignment="Left" Height="50" FontSize="24" Click="Click"/>
            </StackPanel>

        </Grid>

        <Grid Grid.Column="1"> <!--FEATURES-->

            <Grid Name="FEATURE1">
                <!-- FEATURE 1-->
            </Grid>

            <Grid Name="FEATURE2">
                <!-- Empty, not yet implemented-->
            </Grid>

            <Grid Name="FEATURE3">

                <TabControl>

                    <TabItem Header="A">
                        <ListView x:Name="ALB" ScrollViewer.HorizontalScrollBarVisibility="Disabled" 
                        Margin="10" ItemTemplate="{DynamicResource DataTemplate1}" 
                        Background="{x:Null}" BorderBrush="{x:Null}" Foreground="{x:Null}" Grid.Row="0">
                            <ListBox.ItemContainerStyle>
                                <Style TargetType="ListBoxItem">
                                    <Setter Property="Padding" Value="0"/>
                                    <Setter Property="Margin" Value="6"/>
                                </Style>
                            </ListBox.ItemContainerStyle>
                            <ListBox.ItemsPanel>
                                <ItemsPanelTemplate>
                                    <WrapPanel/>
                                </ItemsPanelTemplate>
                            </ListBox.ItemsPanel>
                        </ListView>
                    </TabItem>

                    <TabItem Header="B">
                        <ListView x:Name="BLB" ScrollViewer.HorizontalScrollBarVisibility="Disabled" 
                        Margin="10" ItemTemplate="{DynamicResource DataTemplate1}" 
                        Background="{x:Null}" BorderBrush="{x:Null}" Foreground="{x:Null}" Grid.Row="0">
                            <ListBox.ItemContainerStyle>
                                <Style TargetType="ListBoxItem">
                                    <Setter Property="Padding" Value="0"/>
                                    <Setter Property="Margin" Value="6"/>
                                </Style>
                            </ListBox.ItemContainerStyle>
                            <ListBox.ItemsPanel>
                                <ItemsPanelTemplate>
                                    <WrapPanel/>
                                </ItemsPanelTemplate>
                            </ListBox.ItemsPanel>
                        </ListView>
                    </TabItem>

                    <TabItem Header="C">
                        <ListView x:Name="CLB" ScrollViewer.HorizontalScrollBarVisibility="Disabled" 
                        Margin="10" ItemTemplate="{DynamicResource DataTemplate1}" 
                        Background="{x:Null}" BorderBrush="{x:Null}" Foreground="{x:Null}" Grid.Row="0">
                            <ListBox.ItemContainerStyle>
                                <Style TargetType="ListBoxItem">
                                    <Setter Property="Padding" Value="0"/>
                                    <Setter Property="Margin" Value="6"/>
                                </Style>
                            </ListBox.ItemContainerStyle>
                            <ListBox.ItemsPanel>
                                <ItemsPanelTemplate>
                                    <WrapPanel/>
                                </ItemsPanelTemplate>
                            </ListBox.ItemsPanel>
                        </ListView>
                    </TabItem>

                    <TabItem Header="D">
                        <ListView x:Name="DLB" ScrollViewer.HorizontalScrollBarVisibility="Disabled" 
                        Margin="10" ItemTemplate="{DynamicResource DataTemplate1}" 
                        Background="{x:Null}" BorderBrush="{x:Null}" Foreground="{x:Null}" Grid.Row="0">
                            <ListBox.ItemContainerStyle>
                                <Style TargetType="ListBoxItem">
                                    <Setter Property="Padding" Value="0"/>
                                    <Setter Property="Margin" Value="6"/>
                                </Style>
                            </ListBox.ItemContainerStyle>
                            <ListBox.ItemsPanel>
                                <ItemsPanelTemplate>
                                    <WrapPanel/>
                                </ItemsPanelTemplate>
                            </ListBox.ItemsPanel>
                        </ListView>
                    </TabItem>

                </TabControl>

            </Grid>
        </Grid>
    </Grid>
</Window>

MainWindow.xaml.cs:

namespace A
{
    public partial class MainWindow : Window
    {
        #region ATTRIBUTES
        Button[] Tabs;
        Grid[] Grids;
        bool[] loaded;

        const int nbTabs = 3;
        enum Features { FEATURE1 = 0, FEATURE2 = 1, FEATURE3 = 2 };

        FEATURE3 FEATURE3;
        #endregion

        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = this;


            #region NAVIGATION SETUP
            Tabs = new Button[nbTabs];
            Grids = new Grid[nbTabs];
            loaded = new bool[nbTabs];

            Tabs[0] = FEATURE1Button;
            Grids[0] = FEATURE1;

            Tabs[1] = FEATURE2Button;
            Grids[1] = FEATURE2;

            Tabs[2] = FEATURE3Button;
            Grids[2] = FEATURE3;

            show((int)Features.FEATURE1, true);
            #endregion

            FEATURE3 = new FEATURE3();

            ALB.ItemsSource = FEATURE3.A;
            BLB.ItemsSource = FEATURE3.B;
            CLB.ItemsSource = FEATURE3.C;
            DLB.ItemsSource = FEATURE3.D;
        }

        #region NAVIGATION
        private void show(int index, bool showing)
        {
            FontWeight fw = FontWeights.Normal;
            Visibility vsb = Visibility.Collapsed;
            if (showing)
            {
                fw = FontWeights.Bold;
                vsb = Visibility.Visible;
                for (int i = (index + 1) % nbTabs; i != index; i = (i + 1) % nbTabs) show(i, false);
            }
            Tabs[index].SetValue(TextBlock.FontWeightProperty, fw);
            Grids[index].Visibility = vsb;
        }

        private void Click(object sender, RoutedEventArgs e)
        {
            for (int i = 0; i < Tabs.Length; i++)
                if (sender.Equals(Tabs[i]))
                {
                    show(i, true);

                    if (i == 0 && !loaded[i]) loadFEATURE1();
                    if (i == 1 && !loaded[i]) loadFEATURE2(); 
                    if (i == 2 && !loaded[i]) loadFEATURE3();

                    loaded[i] = true;

                    break;
                }
        }
        #endregion
        private async void loadFEATURE1()
        {
            //Loads FEATURE3, works perfectly
        }

        private async void loadFEATURE2()
        {
            //Currently empty, not yet implemented
        }

        private async void loadFEATURE3()
        {
            await FEATURE3.getAll(6);// gets 6 more items;
        }
    }

    public class FEATURE3 
    {
        // Items in a are also either b, c or d. Each item in a are also in one and only one of the 3 other ObservableCollection
        ObservableCollection<ITEM> a; 
        ObservableCollection<ITEM> b;
        ObservableCollection<ITEM> c;
        ObservableCollection<ITEM> d;

        public ObservableCollection<ITEM> A { get => a; set => a = value; }
        public ObservableCollection<ITEM> B { get => b; set => b = value; }
        public ObservableCollection<ITEM> C { get => c; set => c = value; }
        public ObservableCollection<ITEM> D { get => d; set => d = value; }

        public FEATURE3()
        {
            a = new ObservableCollection<ITEM>();
            b = new ObservableCollection<ITEM>();
            c = new ObservableCollection<ITEM>();
            d = new ObservableCollection<ITEM>();
        }


        public async Task getAll(int n)
        {
            //Fills a,b,c,d with n items. Works perfectly.
        }

    }

    public class ITEM
    {
        int id;
        string name;
        BitmapImage image;

        public int Id { get => id; set => id = value; }
        public string Name { get => name; set => name = value; }
        public BitmapImage Image { get => image; set => image = value; }
    }
}

Я не знаю, где и почему у меня есть эти проблемы.Есть ли у вас какие-либо советы о том, с чего начать или решения этой проблемы? Спасибо.

РЕДАКТИРОВАТЬ: Я до сих пор не знаю, что вызвало проблему, но я исправил ее с помощью архитектуры MVVM

1 Ответ

0 голосов
/ 12 июня 2019

Для вашего 2-го выпуска ваш класс должен реализовать INotifyPropertyChanged, чтобы элемент, добавленный в ваш источник предметов, мог уведомить представление об обновлении.Самый простой способ сделать это - установить пакет Fody https://www.nuget.org/packages/Fody/. Он закачает INotifyPropertyChanged для вас.

Руководство по использованию: https://github.com/Fody/Home/blob/master/pages/usage.md

Это довольно легко использовать.

...