오래된 게시물에 답글 달아서 끌올! ㅋㅅㅋ~
@jamesnet214 근데
요기서 CommandParameter="{Binding RelativeSource Self}"
하시면 안 됩니닷
이렇게 하면 작성하신 MyViewModel
처럼
ViewModel 안에서 View 객체를 획득하게 되지욤. 이러면 패턴을 깨는 행위가 되어욜.+ㅁ+ ;;
만약 ListViewItem 의 DataContext 를 넘기고 싶다면
CommandParameter="{Binding}"
요러케만 하셔도 되겠죵?
그리고 @SangHyeon.Kim 하신 방법이 사실 가장 정석적인 방법인데
뎁스가 깊어지다보면 Model 을 직접 ViewModel 로 사용하는 ItemTemplate 들이 생겨나게 되지요.
예를 들면
public class UserGroup
{
public ObservableCollection<User> Users { get; } // ListView 의 ItemsSource 로 binding
}
public class User // <-- 결국 이 타입이 ListViewItem 의 ViewModel 이 됨.
{
public string Id { get; set; }
public string Name { get; set; }
}
요런식으로 간단하게 예를 들자면
RelativeSource 없이 Remove command 을 정의한다고 하면
ICommand 와 그 멤버 선언을 User 타입에 해줘야 하는 상황이 발생해요.
public class User // 요따우 로?
{
...
private RelayCommand _removeCommand;
public ICommand RemoveCommand => _removeCommand ?? (_removeCommand = new RelayCommand(Remove, CanRemove));
private void Remove(object user)
{
// 부모 UserGroup 에서 자기 자신 삭제?
}
}
이건 논란의 여지가 있을 수 있는데
User 타입을 단순히 Model 의 컨텍스트 정도로 바라본다면
User 타입 내부에 UserGroup 의 View 를 핸들링하는 Command 를 작성하는 건 적절하지 않을 수 있어요.
그래서 개인적으로는 RelativeSource 를 이용하는 게 일반적으로는 맞다고 보는데
이게 복잡한 템플릿 속에서 막 이것저것 연결되다보면
그 RelativeSource 로 부모와 조상을 찾는 것에서 버그가 발생할 가능성이 높기도 하거등요.
그래서 저는 간단한 구조일 경우에는 RelativeSource 를 이용해 Command binding 을 하고
복잡하거나 정리가 필요한 상황에서는 별도의 Command Context 를 static 으로 정의해 사용하는 편이에욤
public static class UserGroupCommandBag
{
private static RelayCommand _removeUserCommand;
public static ICommand RemoveUserCommand => _removeCommand ?? (_removeCommand = new RelayCommand(Remove, CanRemove));
private static void RemoveUser(object user)
{
// 요기서 UserGroup 객체를 찾아서 직접 처리하거나
// ObservableRecepient or pubsub같은 걸루 메시지를 쏘고 그걸 UserGroup 에서 받아서 처리합니닷
}
}
요런거 하나 정의해두고 view 에서 사용할 때에는
<DataTemplate x:Key="ListViewItem1">
<Button Command="{x:Static UserGroupCommandBag.RemoveUserCommand}"
CommandParameter="{Binding}"/>
</DataTemplate>
요런 식으루 사용해열. ㅇㅅㅇ/
(예시로 든건 의사코드입니닷. 아이디어 차원에서 봐주세욤 ㅋㅅㅋ)
와…
써놓고 보니 엄청 길군요… -ㅂ-;;;