2016-12-28 3 views
1

У меня есть listview в wpf, который заполняется sql-запросом. Я создал класс под названием «Перевозчик» и определил его так.Динамическое удаление элемента из наблюдаемой коллекции - WPF

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); 
     } 
} 

Я пропустил все декларации переменных, ради пространства.

Мой МОФ выглядит следующим образом:

enter image description here

Каждый «узел» имеет различное количество носителей, и в зависимости от выбранного узла, список несущей изменяется соответствующим образом. Список носителей привязан к наблюдаемому коллекциям с именем CarrierList.

Вот 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. Тем не менее, я не понимаю, как удалить элемент из коллекции из объекта объекта.

ответ

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); 
    } 
+0

Когда я устанавливаю его так, ничего не происходит, когда я нажимаю X. У меня есть точка останова, установленная в модели представления для моей функции RemoveCarrierFromNode, и она никогда не попадает. –

+0

вместо 'string' введите тип, который вы проходите через DeleteGateCommand a Carrier. – mrsargent

+0

. Ах, я пропустил, что вы меняли имя ListView, я думал, что я привязывал его к исходному источнику источников ... спасибо за помощь. –

1

Это является довольно распространенным узором и вам нужно всего лишь несколько изменений, чтобы сделать его Работа. Во-первых, я бы действительно сделал командную часть Remove модели просмотра. Если вы этого не сделаете, то, как вы заметили, вам понадобится каждый элемент Carrier, чтобы иметь ссылку на его коллекцию, которая была бы довольно неэффективной и могла бы легко привести к утечкам памяти.

Когда вы привяжите Remove кнопку на Remove команды вашей модели представления, необходимо указать полный путь к модели представления в качестве источника, так как DataContext из ListViewItem является Carrier не View Model. Один из способов, вы могли бы сделать это, чтобы дать вашему 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); 

, потому что вы хотите, чтобы параметр команды, чтобы быть объектом Carrier, а не его имя.

Надеюсь, это поможет!

Смежные вопросы