具有两个(几乎相似)模板的两个列表框

问题描述 投票:-1回答:2

我有2个具有2个数据模板的列表框,它们几乎相同,除了其中一个包含TextBox而不是ComboBox。

第一个模板:

<DataTemplate x:Key="OldPanelsTemplate" DataType="{x:Type VM:CustomPanelBoard}">
    <Grid Height="60" Margin="0">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="35"/>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="Auto"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Border Height="60" Grid.RowSpan="2" VerticalAlignment="Center" HorizontalAlignment="Center" BorderBrush="Blue" BorderThickness="1" Width="35" Background="Blue"
                Margin="0 0 2 0" >
            <TextBlock  Foreground="White" VerticalAlignment="Center" HorizontalAlignment="Center" Background="Blue" 
                        Text="{Binding RelativeSource={RelativeSource AncestorType=ListBoxItem, Mode=FindAncestor}, Path=(ItemsControl.AlternationIndex), 
                Converter={StaticResource IncrementerConverter}}" />
        </Border>
        <TextBlock Grid.Column="1" Text="{Binding Name}" />
        <TextBlock Grid.Column="2" Text="{Binding DistributionSystemName}"/>
        <TextBlock Grid.Row="1" Grid.Column="1" Text="Number of circuits to be copied: "/>
        <TextBlock Grid.Row="1" Grid.Column="2" Text="{Binding NumberOfCircuitsToBeCopied}" />
    </Grid>
</DataTemplate>

第二个模板:

<DataTemplate x:Key="NewPanelsTemplate" DataType="{x:Type VM:CustomPanelBoard}">
    <Grid Height="60">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="35"/>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="Auto"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Border Height="60" Grid.RowSpan="2" VerticalAlignment="Center" HorizontalAlignment="Center" BorderBrush="Blue" BorderThickness="1" Width="35" Background="Blue"
                Margin="0 0 2 0" >
            <TextBlock  Foreground="White" VerticalAlignment="Center" HorizontalAlignment="Center" Background="Blue" 
                        Text="{Binding RelativeSource={RelativeSource AncestorType=ListBoxItem, Mode=FindAncestor}, Path=(ItemsControl.AlternationIndex), 
                Converter={StaticResource IncrementerConverter}}" />
        </Border>
        <TextBlock Grid.Column="1" Text="{Binding Name}" />
        <ComboBox Grid.Column="2" ItemsSource="{Binding ValidDistributionSystemsForPanel}" 
                  SelectedItem="{Binding SelectedValidDistributionSystemsForPanel}" HorizontalAlignment="Stretch"  
                  IsHitTestVisible="{Binding DistributionSystemNotAssigned}" IsEnabled="{Binding DistributionSystemNotAssigned}" 
                  ItemTemplate="{StaticResource DistributionSystemTemplate}" >
        </ComboBox>
        <TextBlock Grid.Row="1" Grid.Column="1" Text="Number of available ways: "/>
        <TextBlock Grid.Row="1" Grid.Column="2" Text="{Binding NumberOfAvailableWays}" />
    </Grid>
</DataTemplate>

您可以看到,除了这部分,它们几乎都是相同的:

<ComboBox Grid.Column="2" ItemsSource="{Binding ValidDistributionSystemsForPanel}" 
                  SelectedItem="{Binding SelectedValidDistributionSystemsForPanel}" HorizontalAlignment="Stretch"  
                  IsHitTestVisible="{Binding DistributionSystemNotAssigned}" IsEnabled="{Binding DistributionSystemNotAssigned}" 
                  ItemTemplate="{StaticResource DistributionSystemTemplate}" >
        </ComboBox>

问题是,无论何时我更改其中一个的任何内容,我都必须同时更改另一个内容...以某种方式可以合并它们并使组合框成为唯一根据哪个列表框更改的变量的任何方式调用模板?

wpf data-binding listbox datatemplate listboxitem
2个回答
0
投票

这里是您如何实现这一目标的尝试,但是我不得不承认这很麻烦,但是盲目地回答了您的问题!更好的方法是正确实现DataTemplateSelector

想法是将变化的部分分解为两个单独的DataTemplates并将它们放入资源中,其中一个带Combobox,一个带给TextBlock

<DataTemplate x:Key="DataTemplateCombobox">
        <ComboBox  ItemsSource="{Binding ValidDistributionSystemsForPanel}" ...>
        </ComboBox>
</DataTemplate>
<DataTemplate x:Key="DataTemplateTextblock" >
        <TextBlock Text="{Binding DistributionSystemName}" ... />
</DataTemplate>

现在这些控件将在您的主(通用)ContentPresenter中替换为DataTemplateContentPresenter使用ContentTemplateSelector根据应用了ListBoxDataTemplate的名称来选择要使用的子数据模板,这就是Content直接绑定到ListBox的原因使用祖先绑定:

 <local:ValueDataTemplateSelector x:Key="TemplateSelector" 
                                     DefaultDataTemplate="{StaticResource DataTemplateTextblock}" 
                                     ComboboxDataTemplate="{StaticResource DataTemplateCombobox}" 
                                     TextBlockDataTemplate="{StaticResource DataTemplateTextblock}" />
    <DataTemplate x:Key="OldPanelsTemplate">
        <Grid Height="60" Margin="0" Name="OldPanelsTemplateGrid" >
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="35"/>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="Auto"/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
            <Border Height="60" Grid.RowSpan="2" VerticalAlignment="Center" HorizontalAlignment="Center" BorderBrush="Blue" BorderThickness="1" Width="35" Background="Blue"
                    Margin="0 0 2 0" >
                <TextBlock  Foreground="White" VerticalAlignment="Center" HorizontalAlignment="Center" Background="Blue" Text="tex" />
            </Border>
            <TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Name}" />
            <ContentPresenter ContentTemplateSelector="{StaticResource TemplateSelector}" Content="{Binding RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}" Grid.Row="0" Grid.Column="2">

            </ContentPresenter>
            <TextBlock Grid.Row="1" Grid.Column="1" Text="Number of circuits to be copied: "/>
            <TextBlock Grid.Row="1" Grid.Column="2" Text="{Binding NumberOfCircuitsToBeCopied}" />
        </Grid>
    </DataTemplate>

以及这里DataTemplateSelector的实现方式(基本上):

public class ValueDataTemplateSelector : DataTemplateSelector
{
    public DataTemplate DefaultDataTemplate { get; set; }
    public DataTemplate ComboboxDataTemplate { get; set; }
    public DataTemplate TextBlockDataTemplate { get; set; }

    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        var lb = item as ListBox;

        if (lb is null)
            return DefaultDataTemplate;

        if (lb.Name == "ListOne")
            return ComboboxDataTemplate;
        if (lb.Name == "ListTwo")
            return TextBlockDataTemplate;
        return DefaultDataTemplate;
    }
}

最后,由于ContentContentPresenter直接绑定到ListBox,因此您的子DataTemplates丢失了其DataContext,因此只需使用DataContext绑定或其他方法再次钩住其ElementName:] >

 <DataTemplate x:Key="DataTemplateCombobox">
        <ComboBox DataContext="{Binding ElementName=OldPanelsTemplateGrid, Path=DataContext}"  ItemsSource="{Binding ValidDistributionSystemsForPanel}" >
        </ComboBox>
    </DataTemplate>
    <DataTemplate x:Key="DataTemplateTextblock" >
        <TextBlock Text="{Binding DistributionSystemName}"  DataContext="{Binding ElementName=OldPanelsTemplateGrid, Path=DataContext}"/>
    </DataTemplate>

[OldPanelsTemplateGrid是主DataTemplate中的第一个网格,应该具有有效的ListBoxItem DataContext

这里是完整的Xaml代码:

            </ContentPresenter>
            <TextBlock Grid.Row="1" Grid.Column="1" Text="Number of circuits to be copied: "/>
            <TextBlock Grid.Row="1" Grid.Column="2" Text="{Binding NumberOfCircuitsToBeCopied}" />
        </Grid>
    </DataTemplate>

</Window.Resources>
<!--DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorLevel=2,AncestorType=DataTemplate}}"-->
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>

    <ListBox x:Name ="ListOne" ItemsSource="{Binding MyCollection}" ItemTemplate="{StaticResource OldPanelsTemplate}"/>
    <ListBox x:Name ="LisTwo"  ItemsSource="{Binding MyCollection}" ItemTemplate="{StaticResource OldPanelsTemplate}" Grid.Row="1"/>
</Grid>


0
投票

我设法通过将它们合并到一个模板中来解决它:

© www.soinside.com 2019 - 2024. All rights reserved.