使用c#WPF绑定xaml中的嵌套可观察集合

yptwkmov  于 2022-12-07  发布在  C#
关注(0)|答案(2)|浏览(264)

我有一个困难的时间试图弄清楚如何在xaml绑定一个嵌套的Observable Collection。PLC类包含标签。这可能是熟悉的,如果你在自动化工作。我已经标记了代码的区域,我有麻烦说“***!不能搞清楚这个***"。我是新的xaml,并试图在xaml中做绑定。如果它不能在xaml中完成,代码隐藏解决方案会很有帮助。

PLC类别

public class PLC
{
    public string Name { get; set; }
    public ObservableCollection<Tag> Tags { get; set; }
    public PLC(string name)
    {
        Name = name;
        Tags = new ObservableCollection<Tag>();
    }
    public override string ToString()
    {
        return Name;
    }
}

Tag Class当您单击PLC时,右侧ListView中的PLC的tag将获取与该PLC相关的tag。

public class Tag
{
    public Tag(string name, int value)
    {
        Name = name;
        Value = value;
    }
    public string Name { get; set; }
    public int Value { get; set; }
}

xaml-注意,这是绑定到父视图模型的用户控件。

<UserControl x:Class="Test.UserControls.RuntimeControl"
             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="450" d:DesignWidth="800">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="20"></RowDefinition>
            <RowDefinition Height="*"></RowDefinition>
        </Grid.RowDefinitions>
        <Grid Grid.Row="0">
            <TextBlock Foreground="Red" Margin="10,0,0,0" >Runtime</TextBlock>
        </Grid>
        <Grid Grid.Row="1">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"></ColumnDefinition>
                <ColumnDefinition Width="*"></ColumnDefinition>
            </Grid.ColumnDefinitions>
            <ListView x:Name="PLCLV" Grid.Column="0" Margin="10" FontSize="25" SelectionMode="Single" ScrollViewer.VerticalScrollBarVisibility="Visible"
                      BorderThickness="0" ItemsSource="{Binding PLCs}">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Name}"></TextBlock>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
            <ListView Grid.Column="1" Margin="10" FontSize="25" AlternationCount="2" ScrollViewer.VerticalScrollBarVisibility="Visible"
                      BorderThickness="0 " ItemsSource=***!Can't Figure this out!***>
                <ListView.ItemContainerStyle>
                    <Style TargetType="ListViewItem">
                        <Setter Property="Focusable" Value="false"/>
                    </Style>
                </ListView.ItemContainerStyle>
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <TextBlock>
                            <Run Text = "Name: "/>
                            <Run Text =***!Can't Figure this out!***
                            <Run Text ="Value: "/>
                            <Run Text =***!Can't Figure this out!***
                        </TextBlock>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </Grid>
    </Grid>
</UserControl>

在UserControl xaml应答中修复标记为已接受的

<ListView Grid.Column="1" Margin="10" FontSize="25" 
DataContext="{Binding SelectedItem, ElementName=PLCLV}" 
ItemsSource="{Binding Tags}">
gudnpqoy

gudnpqoy1#

首先:在名为ListView的“PLCLV”上通过PLC列表设置ItemsSource,因此该ListView的SelectedItem中的对象类型必须为PLC类型(或空),您可以使该SelectedItem成为Tag列表的源。

<ListView Grid.Column="1" Margin="10" FontSize="25" AlternationCount="2" ScrollViewer.VerticalScrollBarVisibility="Visible"
                      BorderThickness="0 " ItemsSource="{Binding SelectedItem.Tags, ElementName=PLCLV}">
            <!-- Or SelectedItem.(local:PLC.Tags), the "(local:PLC.Tags)" means "the speicified property of specified type on unspecified type boxed property" -->
            <!-- you can use Binding.ElementName to find the sepcified "Name/x:Name" named element in visual tree to be the Binding source -->
                <ListView.ItemContainerStyle>
                    <Style TargetType="ListViewItem">
                        <Setter Property="Focusable" Value="false"/>
                    </Style>
                </ListView.ItemContainerStyle>
                <ListView.ItemTemplate>
                    <!-- "x:Type" is a speicial markup for return a specific "Type" object -->
                    <!-- Set DataType of DataTemplate can help XAML editor show IntelliSense to help you -->
                    <!-- "local:" is a prefix of namespace for the type in xml, defined by "xmlns:", here make the editor know the this DataTemplate is apply on the "Tag" type -->
                    <DataTemplate DataType="{x:Type local:Tag}">
                        <TextBlock>
                            <Run Text="Name: "/>
                            <Run Text="{Binding Name}" />
                            <Run Text="Value: "/>
                            <Run Text="{Binding Value}" />
                        </TextBlock>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>

或者,使用DataContext和ItemsSource:

<ListView Grid.Column="1" Margin="10" FontSize="25" AlternationCount="2" ScrollViewer.VerticalScrollBarVisibility="Visible"
          BorderThickness="0"
          DataContext="{Binding SelectedItem, ElementName=PLCLV}"
          ItemsSource="{Binding Tags}">
          <!-- Or ItemsSource="{Binding Path=(local:PLC.Tags)}" -->
...
yqkkidmi

yqkkidmi2#

假设UserControl的DataContext设置正确(即PLCs的绑定正确)
在代码隐藏中将此属性添加到PLCs集合属性下(稍后在代码隐藏中可能需要它)

private PLC _selectedPlc;
public PLC SelectedPlc
{
    get => _selectedPlc;
    set 
    {
        _selectedPlc = value;
        OnPropertyChanged(nameof(SelectedPlc)); // this will update the second ListView
    }
}
public ObservableCollection PLCs {set; get;} // you have this already

第一个ListView可以看到所有PLC。让我们将第二个ListView的DataContext与SelectedPlc属性绑定,这样,第二个ListView将只能看到一个PLC。

<ListView x:Name="PLCLV" Grid.Column="0" Margin="10" FontSize="25" SelectionMode="Single" ScrollViewer.VerticalScrollBarVisibility="Visible"
          BorderThickness="0" ItemsSource="{Binding PLCs}"
          SelectedItem="{Binding SelectedPlc}">
    <ListView.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Name}" Foreground="{Binding ForegroundColor}"></TextBlock>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

<ListView Grid.Column="1" Margin="10" FontSize="25" AlternationCount="2" ScrollViewer.VerticalScrollBarVisibility="Visible"
          BorderThickness="0" 
          DataContext="{Binding SelectedPlc}"
          ItemsSource="{Binding Tags}">
    <ListView.ItemContainerStyle>
        <Style TargetType="ListViewItem">
            <Setter Property="Focusable" Value="false"/>
        </Style>
    </ListView.ItemContainerStyle>
    <ListView.ItemTemplate>
        <DataTemplate>
            <TextBlock>
                <Run Text= "Name: "/>
                <Run Text="{Binding Name}"
                <Run Text="Value: "/>
                <Run Text="{Binding Value}"
            </TextBlock>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

不要忘记用一些数据填充PLCs(以及每个PLC内的Tags)集合!
注意:PLC类中缺少ForegroundColor属性!

相关问题