2011-10-25 3 views
0

ItemsControl이 포함 된 Silverlight 페이지가 있습니다. 그것은 [Edit], [Delete][Add] 버튼입니다이Silverlight ItemsControl에서 항목을 삭제하기위한 패턴

-- Name    Description   [Add] 
-- Thing1   The first thing  [Edit] [Delete] 
-- Thing2   The second thing  [Edit] [Delete] 

같이 보입니다.

현재 컨트롤을 Thing 컬렉션에 바인딩하고 템플릿을 사용하여 속성을 표시하고 내 ViewModel의 Edit 명령에 바인딩합니다.

ThingViewModelDelete 명령을 사용하면 자체를 삭제할 수 없습니다.

  • 청소하지 않는 것
  • 가 컬렉션에서 자신을 제거 할 수 없습니다 그래서 컬렉션이라는 것은 모르는

어떤 일이 묶을 수있는 가장 좋은 패턴 년대 [Delete] 버튼?

+0

WPF에서는 'RelativeSource'를 사용하여 Delete 버튼을 부모의 datacontext에있는 Delete 명령에 바인딩 할 수 있습니다. 불행히도 Silverlight의'RelativeSource'는 절름발이이고 절반은 쓸데없는 것 같습니다. –

답변

1

다음은 내가 간략하게 설명한 것입니다. RelativeSource을 사용할 수없는 경우는 확실한 선택입니다.

  • 이름 부모/수집
  • 에 결합하는 컨트롤은 아이에 대한 바인딩/항목

이는 ItemsControl 작동하지만 수 없었던에 ElementName 속성을 지정 이 패턴이 아직 DataGrid에서 작동하도록하십시오.

<ItemsControl Name="MyParentControl" 
       ItemsSource="{Binding Things}"> 
    <ItemsControl.ItemTemplate> 
     <DataTemplate> 
      <Button Content="Delete" 
        Command="{Binding ElementName=MyParentControl, 
         Path=DataContext.DeleteCommand}" /> 
     </DataTemplate> 
    </ItemsControl.ItemTemplate> 
</ItemsControl> 
+0

그리고 나는'CommandParameter = "{Binding}"'이 필요하다고 생각합니다. – Heiner

1

"삭제"코드는 컬렉션의 개별 항목에 대한 ViewModel에서 실행되지 않고 콜렉션이 포함 된 ViewModel에 버블 링 (버림)되고 거기에서 처리됩니다.

의사 코드 : 버블 링 이벤트에

public class ItemContainerViewModel 
{ 
    List<ItemClass> Items { get; set; } 

    public void DeleteItem(ItemClass item) 
    { 
     this.Items.Remove(item); 
     NotifyOfPropertyChange(() => this.Items); // Causes controls bound to this list to refresh their contents 
    } 
} 

한 가지 방법은 Caliburn.Micro 또는 같은 MVVM 프레임 워크에 더 나은 방법이

public class ItemViewModel 
{ 
    public ItemsCollectionViewModel ParentViewModel { get; private set; } 
    public ItemViewModel(ItemsCollectionViewModel parentViewModel) 
    { 
     this.ParentView = parentViewModel; 
    } 

    public void Delete() 
    { 
     this.ParentViewModel.Delete(this); 
    } 
} 

있다가 부모의 ViewModel

년대의 ItemViewModel 인식을하는 것입니다 MVVM-Lite,하지만 적어도 당신의 ViewModel에서 이러한 종류의 작업에 대해 생각하는 방법을 배우게됩니다.

Essentialy - ViewModel은 어떤 종류의보기 없이도 모든 사용자 작업을 수행 할 수 있어야합니다. 일부 테스트 코드를 실행하고 바운드 뷰없이 의도 한대로 VM을 작동 할 수 있어야합니다.

0

사용자가 행을 선택하고 다음 명령을 포함하는 VM에 명령을 입력 할 수 있도록 목록 상자를 사용하는 경우 컬렉션, 당신은 깨끗한 구현을 얻을.

여기에 삭제 버튼이있는 행의 xaml입니다. 트릭은 "RelativeSource"

<ListBox ItemsSource="{Binding MyItems, UpdateSourceTrigger=PropertyChanged}" SelectedItem="{Binding MySelectedItem, UpdateSourceTrigger=PropertyChanged}" > 
     <ListBox.ItemContainerStyle> 
      <Style TargetType="{x:Type ListBoxItem}"> 
       <Setter Property="Template"> 
        <Setter.Value> 
         <ControlTemplate TargetType="{x:Type ListBoxItem}"> 
          <StackPanel Orientation="Horizontal" > 
           <Label Content="{Binding}" /> 
           <Button Content="Delete" Command="{Binding DataContext.MyDeleteCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBox}}}" /> 
          </StackPanel > 
         </ControlTemplate> 
        </Setter.Value> 
       </Setter> 
      </Style> 
     </ListBox.ItemContainerStyle> 
    </ListBox> 

그리고 뷰 모델 코드

public DelegateCommand<object> MyDeleteCommand { get; set; } 

protected void DoDelete(object o) 
{ 
    MyItems.Remove(MySelectedItem); 
} 

protected bool CanDoDelete(object o) 
{ 
    return MySelectedItem != null; 
} 

string _mySelectedItem; 
public string MySelectedItem 
{ 
    get { return _mySelectedItem; } 
    set 
    { 
     _mySelectedItem = value; 
     OnPropertyChanged("MySelectedItem"); 
     MyDeleteCommand.RaiseCanExecuteChanged(); 
    } 
} 

ObservableCollection<string> _myItems; 
public ObservableCollection<string> MyItems 
{ 
    get { return _myItems; } 
    set 
    { 
     _myItems = value; 
     OnPropertyChanged("MyItems"); 
    } 
} 

아를 사용하여 DeleteCommand에 부모 항목에있는 버튼을 결합하는 것입니다, 난 그냥 실버 및 relativeSource에 대한 위의 코멘트를 보았다. WPF로이 작업을 수행했는데 작동했는데 실버 라이트에서 작동하지 않을 수 있습니다.

+0

이것은 WPF에서 할 수있는 방법이지만 Silverlight에서는'FindAncestor'가 없습니다. –

관련 문제