我在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看起来像这样:
每个“节点”具有不同数量的载波,并且取决于所选节点,载波列表相应地改变。载体列表被绑定到名为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命令。但是,我对如何从项目对象内部从集合中删除项目感到茫然。
答案 0 :(得分:1)
如果我正确理解您的问题,您是否尝试点击“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>
然后移除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
命令时,需要指定视图模型的完整路径作为源,因为DataContext
的ListViewItem
是Carrier
而不是视图模型。一种方法是给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对象,而不是其名称。
希望这有帮助!