从可观察集合中动态删除项目 - WPF

时间:2016-12-28 19:44:25

标签: c# wpf xaml listview

我在wpf中有一个listview,它由sql查询填充。我创建了一个名为“Carrier”的类,并将其定义为。

public class Carrier
    {
        public Carrier(string rank, string id, string name, string add1, string add2, string add3, string add4)
        {
            _rank = rank + ".";
            _carrierId = id;
            _carrierName = name;
            _address1 = add1;
            _address2 = add2;
            _address3 = add3;
            _address4 = add4;
            OnRemoveClick = new DelegateCommand<string>(RemoveCarrierFromNode);
        }
}

为了空间,我省略了变量的所有声明。

我的wpf看起来像这样:

enter image description here

每个“节点”具有不同数量的载波,并且取决于所选节点,载波列表相应地改变。载体列表被绑定到名为CarrierList的observablecollection。

以下是我的Listview的XAML,它显示了动态标签和按钮的形成方式。

<ListView Margin="134,110,100,50" HorizontalAlignment="Center" Width="232" BorderBrush="LightGray" BorderThickness="1,1,1,1" Visibility="{Binding Path=ShowCarrierList, Converter={StaticResource BoolToVis}}" ItemsSource="{Binding CarrierList}" Grid.RowSpan="2" ScrollViewer.CanContentScroll="True">
            <ListView.ItemTemplate>
                <DataTemplate>
                        <DockPanel Margin="0,0,0,0" HorizontalAlignment ="Stretch">
                            <Grid HorizontalAlignment="Stretch">
                                <Grid.Resources>
                                    <Style TargetType="{x:Type Border}">
                                        <!-- All rows -->
                                        <Setter Property="BorderBrush" Value="Black" />
                                        <Setter Property="BorderThickness" Value="2" />
                                        <Setter Property="CornerRadius" Value="5" />
                                    </Style>
                                </Grid.Resources>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="165" />
                                    <ColumnDefinition Width="20" />
                                    <ColumnDefinition Width="20" />
                                    <ColumnDefinition Width="20" />
                                </Grid.ColumnDefinitions>
                            <TextBlock Text="{Binding Rank}"  />
                            <TextBlock Text="{Binding CarrierName}" Margin="13,0,0,0"/>


                            <Button  Width="20" Grid.Column="1" HorizontalAlignment="Right" ToolTip="Edit Carrier Details">
                                    <StackPanel>
                                        <Image Source="{StaticResource EditImg}"/>
                                    </StackPanel>
                                </Button>
                                <Button  Width="20" Grid.Column="2" HorizontalAlignment="Right" ToolTip="View All Nodes With This Carrier">
                                    <StackPanel>
                                        <Image Source="{StaticResource NetworkImg}"/>
                                    </StackPanel>
                                </Button>
                            <Button  Width="20" Grid.Column="3" HorizontalAlignment="Right" ToolTip="Remove Carrier From Node" Command="{Binding OnRemoveClick}" CommandParameter="{Binding CarrierName}">
                                    <StackPanel>
                                        <Image Source="{StaticResource ErrorImg}"/>
                                    </StackPanel>
                            </Button>
                            </Grid>
                        </DockPanel>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>

单击“X”按钮时,触发的命令必须位于Carrier对象内。我尝试在视图模型中声明命令并且它永远不会被触发,但是当我把它放在Carrier类中时,我能够触发Remove命令。但是,我对如何从项目对象内部从集合中删除项目感到茫然。

2 个答案:

答案 0 :(得分:1)

如果我正确理解您的问题,您是否尝试点击“X”按钮从列表中删除所选项目?如果是这样,我会将DelegateCommandCommandParameter一起使用,如下所示

<ListView x:Name="carrierList">            
        <Button Command="{Binding ElementName=carrierList,Path=DataContext.OnRemoveClick}" CommandParameter="{Binding}">
            <StackPanel>
                <Image Source="{StaticResource ErrorImg}"/>
            </StackPanel>
        </Button>

    </ListView>

然后移除viewmodel

中的项目
 public class MainViewModel
{
    public ICommand OnRemoveClick { get; set; }        

    public MainViewModel()
    {
        OnRemoveClick = new DelegateCommand<Carrier>(RemoveCarrierFromNode);

    }

    public void RemoveCarrierFromNode(object obj)
    {
        CarrierList.Remove(obj);
    }

答案 1 :(得分:1)

这是一种非常常见的模式,您只需要进行一些更改即可使其正常工作。首先,我确实将Remove命令作为视图模型的一部分。如果你不这样做,那么,正如你所注意到的,你会以某种方式需要每个Carrier项来引用它的集合,这将非常不优雅并且很容易导致内存泄漏。

Remove按钮绑定到视图模型的Remove命令时,需要指定视图模型的完整路径作为源,因为DataContextListViewItemCarrier而不是视图模型。一种方法是给ListView一个明确的名称(例如Name="x:_listView"),然后绑定:

Command="{Binding ElementName=_listView, Path=DataContext.OnRemoveClick}"

这将解决视图模型命令未被触发的问题。

其次,改变

CommandParameter="{Binding CarrierName}"

CommandParameter="{Binding}"

OnRemoveClick命令处理程序的参数将是单击其按钮的Carrier对象,现在只需说出CarrierList.Remove(arg)

即可将其删除

最后,你需要改变:

OnRemoveClick = new DelegateCommand<string>(RemoveCarrierFromNode);

OnRemoveClick = new DelegateCommand<Carrier>(RemoveCarrierFromNode);

因为您希望command参数是Carrier对象,而不是其名称。

希望这有帮助!