C# 从可观察集合中动态删除项-WPF
我在wpf中有一个由sql查询填充的listview。我创建了一个名为“Carrier”的类,并这样定义它C# 从可观察集合中动态删除项-WPF,c#,wpf,xaml,listview,C#,Wpf,Xaml,Listview,我在wpf中有一个由sql查询填充的listview。我创建了一个名为“Carrier”的类,并这样定义它 public class Carrier { public Carrier(string rank, string id, string name, string add1, string add2, string add3, string add4) { _rank = rank + "."; _ca
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);
}
}
公共级承运人
{
公共载体(字符串排名、字符串id、字符串名称、字符串地址1、字符串地址2、字符串地址3、字符串地址4)
{
_排名=排名+”;
_carrierId=id;
_carrierName=名称;
_地址1=地址1;
_地址2=地址2;
_地址3=地址3;
_地址4=地址4;
OnRemoveClick=新的DelegateCommand(RemoveCarrierFromNode);
}
}
为了节省空间,我省略了所有变量的声明
我的wpf如下所示:
每个“节点”具有不同数量的载波,并且根据所选节点,载波列表相应地改变。载波列表绑定到一个名为CarrierList的observeCollection
下面是我的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类时,我能够触发Remove命令。但是,我不知道如何从item对象内部从集合中删除该项 如果我正确理解您的问题,您是否试图单击“X”按钮从列表中删除所选项目?如果是这样,我将使用
DelegateCommand
和CommandParameter
如下
<ListView x:Name="carrierList">
<Button Command="{Binding ElementName=carrierList,Path=DataContext.OnRemoveClick}" CommandParameter="{Binding}">
<StackPanel>
<Image Source="{StaticResource ErrorImg}"/>
</StackPanel>
</Button>
</ListView>
这是一种非常常见的模式,您只需进行一些更改即可使其正常工作。首先,我确实将
Remove
命令作为视图模型的一部分。如果您不这样做,正如您所注意到的,您可能需要每个载体
项目都有一个对其集合的引用,这将非常不雅观,并且很容易导致内存泄漏
将Remove
按钮绑定到视图模型的Remove
命令时,需要指定视图模型的完整路径作为源,因为ListViewItem
的DataContext
是载体
而不是视图模型。一种方法是为ListView指定一个显式名称(例如,name=“x:\u ListView”
),然后按如下方式绑定:
Command="{Binding ElementName=_listView, Path=DataContext.OnRemoveClick}"
这将解决视图模型的命令未被激发的问题
第二,改变
CommandParameter="{Binding CarrierName}"
到
然后,OnRemoveClick
命令处理程序的参数将是其按钮被单击的Carrier
对象,现在只需说出CarrierList.Remove(arg)
最后,您需要更改:
OnRemoveClick = new DelegateCommand<string>(RemoveCarrierFromNode);
OnRemoveClick=newdelegateCommand(RemoveCarrierFromNode);
到
OnRemoveClick=newdelegateCommand(RemoveCarrierFromNode);
因为您希望命令参数是载体对象,而不是其名称
希望这有帮助 当我这样设置它时,当我单击X时,什么也不会发生。我在视图模型中为我的RemoveCarrierFromNode函数设置了一个断点,它永远不会被击中。与其使用
string
字符串,不如将通过DeletegateCommand传递的类型设为一个Carrier
啊,我错过了更改ListView名称的机会,我以为我是在把它绑定到原始的itemsource上……谢谢你的帮助。嘿,我们同时写了几乎相同的答案。伟大的头脑。。。
CommandParameter="{Binding}"
OnRemoveClick = new DelegateCommand<string>(RemoveCarrierFromNode);
OnRemoveClick = new DelegateCommand<Carrier>(RemoveCarrierFromNode);