나는 뭔가를 생각해 냈습니다. 나는 비교적 행복합니다. 이로 인해 100 개의 복합 ViewModel을 만들지 못하게되었고 불필요한 복잡성이 생겨도 필자가 작성해야하는 복사/붙여 넣기 코드의 양이 크게 줄어 들었습니다.
VMFactoryViewModel.cs
public class CreatedViewModelEventArgs<T> : EventArgs where T : ViewModelBase
{
public T ViewModel { get; private set; }
public CreatedViewModelEventArgs(T viewModel)
{
ViewModel = viewModel;
}
}
public class VMFactoryViewModel<T> : ViewModelBase where T : ViewModelBase
{
private Func<string, T> _createViewModel;
private RelayCommand<string> _createViewModelCommand;
private readonly IDialogService _dialogService;
/// <summary>
/// Returns a command that creates the view model.
/// </summary>
public ICommand CreateViewModelCommand
{
get
{
if (_createViewModelCommand == null)
_createViewModelCommand = new RelayCommand<string>(x => CreateViewModel(x));
return _createViewModelCommand;
}
}
public event EventHandler<CreatedViewModelEventArgs<T>> CreatedViewModel;
private void OnCreatedViewModel(T viewModel)
{
var handler = CreatedViewModel;
if (handler != null)
handler(this, new CreatedViewModelEventArgs<T>(viewModel));
}
public VMFactoryViewModel(IDialogService dialogService, Func<string, T> createViewModel)
{
_dialogService = dialogService;
_createViewModel = createViewModel;
}
private void CreateViewModel(string viewModelId)
{
try
{
OnCreatedViewModel(_createViewModel(viewModelId));
}
catch (Exception ex)
{
_dialogService.Show(ex.Message);
}
}
}
VMFactoryUserControl.cs
public class VMFactoryUserControl<T> : UserControl where T : ViewModelBase
{
public static readonly DependencyProperty VMFactoryProperty = DependencyProperty.Register("VMFactory", typeof(VMFactoryViewModel<T>), typeof(VMFactoryUserControl<T>));
public VMFactoryViewModel<T> VMFactory
{
get { return (VMFactoryViewModel<T>)GetValue(VMFactoryProperty); }
set { SetValue(VMFactoryProperty, value); }
}
}
GenericView.XAML
<ctrl:VMFactoryUserControl x:Class="GenericProject.View.GenericView"
x:TypeArguments="vm:GenericViewModel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ctrl="clr-namespace:SomeProject.Controls;assembly=SomeProject.Controls"
xmlns:vm="clr-namespace:GenericProject.ViewModel">
<Grid>
<!-- Column Definitions -->
<!-- Row Definitions -->
<Label Grid.Row="0" Grid.Column="0" Content="Generic Id:" HorizontalAlignment="Right" />
<ctrl:CommandTextBox Grid.Row="0" Grid.Column="2"
Command="{Binding VMFactory.CreateViewModelCommand, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"
CommandParameter="{Binding Text, RelativeSource={RelativeSource Self}}" />
<Label Grid.Row="0" Grid.Column="3" Content="Generic Property:" HorizontalAlignment="Right" />
<TextBox Grid.Row="0" Grid.Column="5" IsEnabled="False" Text="{Binding GenericProperty, Mode=OneWay}" />
<!--Additional Read Only Values-->
</Grid>
</ctrl:VMFactoryUserControl>
GenericView.xaml.cs
public partial class GenericView : VMFactoryUserControl<GenericViewModel>
{
public GenericView()
{
InitializeComponent();
}
}
MainPageViewModel.cs
public class MainPageViewModel : ViewModelBase
{
private readonly IDialogService _dialogService;
private GenericViewModel _generic;
private readonly VMFactoryViewModel<GenericViewModel> _genericFactory;
public GenericViewModel Generic
{
get { return _generic; }
private set
{
if (_generic != value)
{
_generic = value;
base.OnPropertyChanged("Generic");
}
}
}
public VMFactoryViewModel<GenericViewModel> GenericFactory
{
get { return _genericFactory; }
}
private void OnGenericFactoryCreatedViewModel(object sender, CreatedViewModelEventArgs<GenericViewModel> e)
{
Generic = e.ViewModel;
}
public MainPageViewModel(IDialogService dialogService)
{
_dialogService = dialogService;
_genericFactory = new VMFactoryViewModel<GenericViewModel>(_dialogService, x => new GenericViewModel(_dialogService, GetGeneric(x)));
_genericFactory.CreatedViewModel += OnGenericFactoryCreatedViewModel;
}
private Generic GetGeneric(string genericId)
{
// Return some Generic model.
}
}
에서 MainPage.xaml
<Page x:Class="GenericProject.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vw="clr-namespace:GenericProject.View">
<StackPanel>
<!-- Headers and Additional Content. -->
<vw:EventView DataContext="{Binding Generic}"
VMFactory="{Binding DataContext.GenericFactory, RelativeSource={RelativeSource AncestorType={x:Type Page}}}" />
</StackPanel>
</Page>
고민중인 부분이 보이지 않습니다. 모델을 뷰 모델에 삽입 할 수없는 이유는 무엇입니까? 왜 TextBox를 깨뜨릴까요? ViewModel이 데이터를 얻는 방법을 변경하면 View에 영향을 미칠 수 있습니다. – BradleyDotNET
@BradleyDotNET 당신이 맞습니다, 내가 보여준 것들이 효과가 있습니다. 그러나 그것은 틀린 것처럼 보인다? 내 뷰 모델의 팩토리를 뷰 모델의 생성으로 덮어 쓴 자리 표시 자 뷰 모델에 삽입해야한다고 생각하지 않습니다. 내 viewmodel과 공장 용으로 두 번째 DataContext를 제공하기 위해 UserControl을 확장 할 수 있을지 궁금해지기 시작 했나요? –
솔직히? 당신의 전체적인 디자인은 어리석게도 복잡하게 보인다. 왜 공장이 필요하니? Btw, 나는 당신이 묘사 한 과정이 대단히 복잡한 것처럼 보인 데 동의한다. 그렇다면 다시 디자인이 그렇게됩니다. – BradleyDotNET