Создавайте StackPanels динамически и обращайтесь к любому из них в коде.

В простейшем виде ...

Я хотел бы создать столько StackPanels, сколько захочу, а затем добавить в них прямоугольники. Затем, чтобы иметь возможность изменить цвет заливки любого из прямоугольников, например, когда я нажимаю кнопку «Пуск». Все в коде позади.

Любая помощь будет оценена.

Например, если бы фреймворк написал наше любимое пиво, я мог бы сделать это так:

XAML:

<Page
    x:Class="Test2.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Test2"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="White">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <StackPanel Orientation="Horizontal">
            <Button Name="StartButton" Content="Start" Click="StartButton_Click" Height="30" Width="200" Margin="5"/>
        </StackPanel>

        <StackPanel Grid.Row="1" Name="myStackPanel" VerticalAlignment="Top"/>

    </Grid>
</Page>

Код позади:

namespace Test2
{
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();

            for (var i = 0; i < 5; i++) // The 5 here could be any number
            {
                myStackPanel.Children.Add(new StackPanel
                {
                    Name = "myPanel" + i,
                    Orientation = Orientation.Horizontal
                });

                for (var j = 0; j < 10; j++) // The 10 here could be any number
                {
                    ("myPanel" + i).Children.Add(new Rectangle
                    {
                        Name = "myRectangle" + i + "-" + j,
                        Fill = new SolidColorBrush(Colors.Black),
                        Width = 20,
                        Height = 20,
                        Margin = new Thickness(1)
                    });
                }
            }
        }

        private void StartButton_Click(object sender, RoutedEventArgs e)
        {
            // E.G. To change the Fill color of Rectangle4 in StackPanel2

            ("myRectangle" + 2 + "-" + 4).Fill = new SolidColorBrush(Colors.Red);
        }
    }
}

person gaw    schedule 19.12.2015    source источник
comment
Это должно вас направить. stackoverflow.com/questions/874380/ .. Вам просто нужно изменить его таким образом, чтобы вы уточняли имя при добавлении и изменении свойств. И, конечно же, вы должны использовать VisualTreeHelper.   -  person tgpdyk    schedule 19.12.2015
comment
Хорошо, спасибо @tgpdyk, я проверю.   -  person gaw    schedule 19.12.2015
comment
@tgpdyk Кажется, у меня возникают ошибки, пытаясь выполнить любое из них: Аргумент 1: невозможно преобразовать из «Windows.UI.Composition.Visual» в «Windows.UI.Xaml.DependencyObject» - я часто нахожу это при обращении к другому документу. Не могли бы вы (или кто-нибудь) быть более конкретным - здесь новичок: (   -  person gaw    schedule 19.12.2015
comment
@gaw Извините, я не понял, что это uwp, я не знаком с этой платформой, поэтому этот ответ может быть или не иметь значения, поэтому я удаляю его. (Я тестировал это в обычном настольном приложении WPF, и он там работает).   -  person pangabiMC    schedule 19.12.2015


Ответы (2)


Во-первых, чтобы добавить формы Rectangle, мы можем создать экземпляр StackPanel и управлять его дочерними элементами:

for (var i = 0; i < 5; i++) // The 5 here could be any number
{
                StackPanel sp = new StackPanel
                {
                    Name = "myPanel" + i,
                    Orientation = Orientation.Horizontal
                };
                myStackPanel.Children.Add(sp);

                for (var j = 0; j < 10; j++) // The 10 here could be any number
                {
                    sp.Children.Add(new Rectangle
                    {
                        Name = "myRectangle" + i + "-" + j,
                        Fill = new SolidColorBrush(Colors.Black),
                        Width = 20,
                        Height = 20,
                        Margin = new Thickness(1)
                    });
                }
}

Затем, чтобы иметь возможность изменить цвет заливки любого из прямоугольников, например, когда я нажимаю кнопку «Пуск». Все в коде позади.

Как упоминалось в tgpdyk, нам нужно использовать VisualTreeHelper, чтобы найти указанную форму прямоугольника.

Класс помощника:

public static class FrameworkElementExtensions
{
        public static T TraverseCTFindShape<T>(DependencyObject root, String name) where T : Windows.UI.Xaml.Shapes.Shape
        {
            T control = null;

            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(root); i++)
            {
                var child = VisualTreeHelper.GetChild(root, i);

                string childName = child.GetValue(FrameworkElement.NameProperty) as string;
                control = child as T;

                if (childName == name)
                {
                    return control;
                }
                else
                {
                    control = TraverseCTFindShape<T>(child, name);

                    if (control != null)
                    {
                        return control;
                    }
                }
            }

            return control;
        }
}

Как это использовать:

private void StartButton_Click(object sender, RoutedEventArgs e)
{
            // E.G. To change the Fill color of Rectangle4 in StackPanel2
            var rec = FrameworkElementExtensions.TraverseCTFindShape<Shape>(myStackPanel, "myRectangle" + 2 + "-" + 4);
            rec.Fill = new SolidColorBrush(Colors.Red);
}

введите описание изображения здесь

Я загрузил свой образец в репозиторий Github

person Franklin Chen - MSFT    schedule 19.12.2015

Это вообще не подход к этому в WPF.

Обычно вы не беспокоитесь о каких-либо компонентах пользовательского интерфейса, а только о данных. В этом случае вы привязываете данные к ItemsControl в список строк, каждая строка содержит список ячеек. Затем в определении ItemsControl вы устанавливаете _ 3_, который содержит еще ItemsControl привязку к ячейкам. Затем во вложенном ItemsControl вы можете установить ItemTemplate, в котором вы привязываете Background к (notifying) ваших ячеек, которое вам нужно просто изменить в коде.

Ознакомьтесь с этими обзорами:

Вы также можете изучить шаблон Model-View-ViewModel, чтобы убедиться в подходящей архитектуре приложения.

person H.B.    schedule 20.12.2015
comment
Здесь будет обзор привязки данных для UWP. Однако в большинстве случаев, если не все, все равно должно быть аналогично. - person H.B.; 20.12.2015
comment
Спасибо за ваш вклад. Я отметил @Franklin Chen - MSFT как ответ, поскольку он очень конкретно ответил на мой вопрос. Однако его реализация заставила меня понять, что мой подход к проблеме, вероятно, не лучший. Тот факт, что он выполняет итерацию по всем прямоугольникам, чтобы найти цель, занимает слишком много времени, когда есть много строк с множеством прямоугольников. Я просмотрю предоставленные вами ссылки и буду бороться. А пока, если у вас есть свободное время, было бы интересно увидеть ваше решение, как мне, так и другим людям, которые борются схожим образом. - person gaw; 20.12.2015
comment
Найти цель, с которой вы хотите эффективно взаимодействовать, - это совсем другая проблема, и она обычно не является проблемой, если вы следуете моему подходу; это сводится к двум доступам к массиву (один для строки, другой для ячейки в указанной строке). Как только вы поймете основы WPF, реализация моего описания станет действительно тривиальной. Прямо сейчас у меня нет среды, в которой я мог бы реализовать это, к сожалению. - person H.B.; 22.12.2015