C# 引用添加到StackPanel的WPF控件

C# 引用添加到StackPanel的WPF控件,c#,wpf,controls,stackpanel,C#,Wpf,Controls,Stackpanel,这是我几天来一直试图解决的问题,但我还没有找到一个好的解决方案 我有一个主WPF窗口,其中包含一个StackPanel。我还有一个名为“MessageManagement”的类,其中包含一个名为“MessagePreview”的自定义WPF控件列表 消息预览 <UserControl x:Class="FinalYearProject.MessagePreview" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/p

这是我几天来一直试图解决的问题,但我还没有找到一个好的解决方案

我有一个主WPF窗口,其中包含一个StackPanel。我还有一个名为“MessageManagement”的类,其中包含一个名为“MessagePreview”的自定义WPF控件列表

消息预览

<UserControl x:Class="FinalYearProject.MessagePreview"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" 
         d:DesignHeight="58" d:DesignWidth="254" Background="White" BorderThickness="1" BorderBrush="#FF320000">
<Grid Name="grid1">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="50" MaxWidth="50" MinWidth="50" />
        <ColumnDefinition Width="197*" MinWidth="20" />
    </Grid.ColumnDefinitions>
    <Grid Grid.Column="1" Name="grid2">
        <Grid.RowDefinitions>
            <RowDefinition Height="31*" />
            <RowDefinition Height="34*" />
            <RowDefinition Height="33*" />
        </Grid.RowDefinitions>
        <Label Content="-ERROR-" Height="28" HorizontalAlignment="Left" Margin="2,1,0,0" Name="senderLabel" VerticalAlignment="Top" Foreground="#FF0000B4" Grid.RowSpan="2" />
        <Label Content="-ERROR-" Height="33" HorizontalAlignment="Left" Name="previewLabel" VerticalAlignment="Top" Margin="-1,17,0,0" Grid.RowSpan="3" />
        <Label Content="-Error-" Grid.Row="1" Height="28" HorizontalAlignment="Left" Margin="0,16,6,0" Name="timeLabel" VerticalAlignment="Top" Grid.RowSpan="2" Width="196" />
    </Grid>
    <Grid Name="grid3">
        <Grid.RowDefinitions>
            <RowDefinition Height="29*" />
            <RowDefinition Height="27*" />
        </Grid.RowDefinitions>
        <Image Height="38" HorizontalAlignment="Center" Margin="3,0,6,20" Name="image1" Stretch="Fill" VerticalAlignment="Bottom" Width="41" Source="/FinalYearProject;component/Images/twitter-bird-light-bgs.png" Grid.RowSpan="2" />
        <CheckBox Height="16" Margin="15,0,22,6" Name="checkBox" VerticalAlignment="Bottom" Grid.Row="1" IsChecked="False" />
    </Grid>
</Grid>
MessagesPanel1是主窗口内的空白堆叠面板

if (!messageManagement.messagesLocked())
{
       foreach (Message m in messageManagement.getListOfMessages()
       {
              MessagesPanel1.Children.Add(m)
       }
}
将自定义控件添加到StackPanel时,会创建原始控件的副本,这意味着更改StackPanel中控件的值不会影响my MessageManagement列表中的控件

是否有一种方法可以引用原始控件,以便它们一起更改?我研究了数据绑定,但我不确定这是否是正确的领域。

如果说“更改”你就意味着数据,在
WPF
中,你永远不需要直接访问
UI
元素,因为它们可能会更改。您需要做的是读取绑定到它们的数据。使用正确的
数据绑定
设置,您将始终更新信息

访问
UI
元素绝非易事,但除此之外,访问数据的方式完全不可靠,因为将控件注入
VisualTree
的方式可能会改变,因此下次更新时代码将失败

例如,关于如何构建可以在此处查看的架构:


同样,您不会在WPF中列出UI元素的
列表。使用
ItemsControl
并将其
ItemTemplate
属性设置为表示项目所需的任何UI:

 <ItemsControl ItemsSource="{Binding Messages}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <!-- Everything you placed in your usercontrol, or else an instance of your usercontrol itself -->
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>


什么?!发布您的xaml和代码。此外,如果您需要一个控件来显示多个项目,这些项目可能是
ItemsControl
或其衍生工具之一(例如
ListBox
),那么您在消息控件中使用的是双向绑定还是单向绑定?我不认为您的控件列表包含控件副本,因为UserControl是一种引用类型……这听起来像是数据绑定的工作。与其让管理器包含自定义控件列表,不如让它只保存数据,例如消息文本。然后使用某种类型的中继器控件(例如ListBox)并创建一个ItemTemplate,以便它对每个项目使用消息控件,并将该中继器绑定到消息集合。这不是一个简单的任务,但是有了一些教程(或者像WPF4这样的好书)就没那么难了。我对我的帖子做了修改,加入了代码,希望这能让问题更清楚一些。
if (!messageManagement.messagesLocked())
{
       foreach (Message m in messageManagement.getListOfMessages()
       {
              MessagesPanel1.Children.Add(m)
       }
}
 <ItemsControl ItemsSource="{Binding Messages}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <!-- Everything you placed in your usercontrol, or else an instance of your usercontrol itself -->
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>