WPF UniformGrid Dynami c содержание - PullRequest
0 голосов
/ 02 марта 2020

У меня есть единообразная сетка, которую я хочу, чтобы отображать содержимое / вид. Может отображать 1, 2, 4 или 6 содержимого. Я установил строку единой сетки, привязку col и привязку видимости содержимого. Это НЕ работает в случае представлений / содержимого, но РАБОТАЕТ в случае прямоугольников. Это почему? Как я могу изменить его для работы с представлениями / содержанием. Пример MainWindow.xaml код .....

<StackPanel>
    <ComboBox HorizontalAlignment="Left" Width="50" SelectedIndex="{Binding SelectedIndex}">
        <ComboBoxItem IsSelected="True" Content="1" />
        <ComboBoxItem Content="2" />
        <ComboBoxItem Content="4" />
        <ComboBoxItem Content="6" />
    </ComboBox>

    <!-- NOT CORRECT, SHOWS 6 ITEMS ALWAYS -->
    <UniformGrid Rows="{Binding ScreenRows}" Columns="{Binding ScreenCols}">
        <local:ScreenView Grid.Row="0" Grid.Column="0" Visibility="{Binding VisibleScreen[0]}" />
        <local:ScreenView Grid.Row="0" Grid.Column="1" Visibility="{Binding VisibleScreen[1]}" />
        <local:ScreenView Grid.Row="0" Grid.Column="2" Visibility="{Binding VisibleScreen[2]}" />
        <local:ScreenView Grid.Row="1" Grid.Column="0" Visibility="{Binding VisibleScreen[3]}" />
        <local:ScreenView Grid.Row="1" Grid.Column="1" Visibility="{Binding VisibleScreen[4]}" />
        <local:ScreenView Grid.Row="1" Grid.Column="2" Visibility="{Binding VisibleScreen[5]}" />
    </UniformGrid>

    <!-- OK, SHOWS 1,2,4, or 6 RECT DEPENDING ON SelectedIndex -->
    <UniformGrid Rows="{Binding ScreenRows}" Columns="{Binding ScreenCols}">
        <Rectangle Width="20" Height="20" Grid.Row="0" Grid.Column="0" Fill="Red" Visibility="{Binding VisibleScreen[0]}" />
        <Rectangle Width="20" Height="20" Grid.Row="0" Grid.Column="1" Fill="Orange" Visibility="{Binding VisibleScreen[1]}" />
        <Rectangle Width="20" Height="20" Grid.Row="0" Grid.Column="2" Fill="Yellow" Visibility="{Binding VisibleScreen[2]}" />
        <Rectangle Width="20" Height="20" Grid.Row="1" Grid.Column="0" Fill="Green" Visibility="{Binding VisibleScreen[3]}" />
        <Rectangle Width="20" Height="20" Grid.Row="1" Grid.Column="1" Fill="Blue" Visibility="{Binding VisibleScreen[4]}" />
        <Rectangle Width="20" Height="20" Grid.Row="1" Grid.Column="2" Fill="Violet" Visibility="{Binding VisibleScreen[5]}" />
    </UniformGrid>

</StackPanel>

По сути, у меня есть выпадающий список. Если я выберу 1, моя ViewModel будет динамически менять строки = 1, столбцы = 1, с 1-м содержимым Visible, а другие свернуты. Это работает в случае прямоугольников, но НЕ просмотров. Это почему? Как это исправить, чтобы он работал для представлений?

Любой, кто-то любопытный, вот код (Prism MVVM) в MainWindowViewModel

class MainWindowViewModel : BindableBase
{
    private const int SCREEN_MAX = 6;

    private int screenRows = 1;
    public int ScreenRows
    {
        get { return screenRows; }
        set { SetProperty(ref screenRows, value); }
    }

    private int screenCols = 1;
    public int ScreenCols
    {
        get { return screenCols; }
        set { SetProperty(ref screenCols, value); }
    }

    private Visibility[] visibleScreen = new Visibility[SCREEN_MAX];
    public Visibility[] VisibleScreen
    {
        get { return visibleScreen; }
        set { SetProperty(ref visibleScreen, value); }
    }

    private int selectedIndex;
    public int SelectedIndex
    {
        get { return selectedIndex; }
        set 
        { 
            SetProperty(ref selectedIndex, value);
            ChangeScreen(selectedIndex);                    
        }
    }

    private void ShowScreens(int num_screens)
    {
        // make all collapse
        for (int i = 0; i < SCREEN_MAX; i++)
            VisibleScreen[i] = Visibility.Collapsed;

        // show only X num screens
        for (int i = 0; i < num_screens; i++)
            VisibleScreen[i] = Visibility.Visible;

        RaisePropertyChanged("VisibleScreen");
    }

    public void ChangeScreen(int idx)
    {
        switch (idx)
        {
            case 0: ScreenRows = 1; ScreenCols = 1; ShowScreens(1); break;
            case 1: ScreenRows = 1; ScreenCols = 2; ShowScreens(2); break;
            case 2: ScreenRows = 2; ScreenCols = 2; ShowScreens(4); break;
            case 3: ScreenRows = 2; ScreenCols = 3; ShowScreens(6); break;
        }
    }
}

ScreenView .xaml

<UserControl...>
    <!-- SOME HOW IT IS THIS DATACONTEXT CODE MESS UP THE UI -->
    <UserControl.DataContext>
        <local:ScreenViewModel x:Name="vm"/>
    </UserControl.DataContext>
    <StackPanel>
        <TextBlock>TEST</TextBlock>
    </StackPanel>
</UserControl>

Пример вывода

enter image description here

Как видно из примера вывода, мой комбинированный выбор равен 1 , поэтому он должен отображать 1 ТЕСТ, в то время как 1 квадрат показывает, что является правильным. Но почему это должно показать мне 6 ТЕСТ? Как заставить его отображать 1 ТЕСТ?

Вот вывод corect

enter image description here

Спасибо!

1 Ответ

0 голосов
/ 02 марта 2020

Начальное значение selectedIndex равно 0 (значение по умолчанию для поля int). Но содержимое массива VisibleScreen не соответствует selectedIndex - вам нужно вызвать ChangeScreen во время инициализации, например, так:

public MainWindowViewModel()
{
    SelectedIndex = 0;
}

Кстати, Grid.Row и Grid.Column не влияют на UniformGrid. UniformGrid упорядочивает элементы в порядке их добавления

Не устанавливайте DataContext внутри UserControls.

вместо Visibility[] создайте коллекцию ScreenViewModel в MainWindowViewModel (ObservableCollection<ScreenViewModel>).

Добавить bool IsVisible свойство в ScreenViewModel.

Изменить метод ShowScreens следующим образом:

private void ShowScreens(int num_screens)
{
    for (int i = 0; i < SCREEN_MAX; i++)
        VisibleScreen[i].IsVisible = i < num_screens ? Visibility.Visible : Visibility.Collapsed;
}

Изменить представление:

<ItemsControl ItemsSource="{Binding VisibleScreen}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
             <UniformGrid Rows="{Binding ScreenRows}" Columns="{Binding ScreenCols}"/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <local:ScreenView Visibility="{Binding IsVisible}"/>
    </ItemsControl.ItemTemplate>
</ItemsControl>

ItemTemplate создаст локальный: ScreenView для каждого элемента в коллекции VisibleScreen и назначить его DataContext локального: ScreenView

...