Fra*_*kyB 13 wpf blend mvvm visual-studio-2013
我正在使用Visual Studio 2013的设计器在WPF中创建我的用户控件,而我正在使用MVVM方法.
我正在尝试找到设置我的viewmodel"Design-Time"的最佳方法,以便我立即看到设计师在更改属性值时的效果.我使用了不同的设计和技术来支持这一点,但没有什么是我想要的.我想知道是否有人有更好的想法......
情况(简化):所以我有一个"设备",我希望UserControl显示状态和操作.从上到下:
bool IsConnected {get;}(和状态变化的适当通知)IsChecked={Binding IsConnected, Mode=OneWay框架:
d:DataContext="{Binding DeviceViewModelDesignTime, Source={StaticResource ViewModelLocator}}"
public class ViewModelLocator
{
private static MainWindowViewModel _mainWindowViewModel;
public MainWindowViewModel MainWindowViewModelMainInstance
{
get
{
if (_mainWindowViewModel == null)
{
_mainWindowViewModel = new MainWindowViewModel();
}
return _mainWindowViewModel;
}
}
public DeviceViewModel DeviceViewModelDesignTime
{
get
{
//Custom initialization of the dependencies here
//Could be to create a FakeDeviceModel and assign to constructor
var deviceViewModel = new DeviceViewModel();
//Custom setup of the ViewModel possible here
//Could be: deviceViewModel.Model = new FakeDeviceModel();
return deviceViewModel;
}
}
Run Code Online (Sandbox Code Playgroud)
解决方案我试过:
编译时解决方案
只需在ViewModelLocator中编写ViewModel的设置.
var deviceViewModel = new DeviceViewModel(fakeDeviceModel);
var fakeDeviceModel = new FakeDeviceModel();
fakeDeviceModel.IsConnected = true;
deviceViewModel.AddDevice(fakeDeviceModel);
Run Code Online (Sandbox Code Playgroud)
优点:简单
缺点:总是要更改代码中的值,重新编译,返回设计器视图,等待结果的更长迭代
资源实例并在ViewModelLocator中保持静态
所以我在XAML中创建了一个实例,并尝试将其推送到设计器使用的当前ViewModel中.不是最干净的方式,但在简单的情况下工作了一段时间(是的,这个集合有一些奇怪的东西,但我的想法是我可以拥有多个设备和当前的设备)
XAML:
<UserControl x:Class="Views.StepExecuteView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DataContext="{Binding DeviceViewModelDesignTime, Source={StaticResource ViewModelLocator}}">
<UserControl.Resources>
<viewModels:DesignTimeDeviceManager x:Key="DesignTimeDeviceManager">
<viewModels:DesignTimeDeviceManager.DesignTimeDevices>
<device:FakeDeviceModel IsConnected="True"
IsBusy="False"
IsTrayOpen="True"
NumberOfChipSlots="4"
/>
</viewModels:DesignTimeDeviceManager.DesignTimeDevices>
[... CheckBox binding to datacontext and so on...]
Run Code Online (Sandbox Code Playgroud)
和ViewModelLocator.cs:
public class ViewModelLocator
{
private static MainWindowViewModel _mainWindowViewModel;
public MainWindowViewModel MainWindowViewModelMainInstance
{
get
{
if (_mainWindowViewModel == null)
{
_mainWindowViewModel = new MainWindowViewModel();
}
return _mainWindowViewModel;
}
}
public static FakeDeviceModel DeviceModelToAddInDesignTime;
public DeviceViewModel DeviceViewModelDesignTime
{
get
{
var deviceViewModel = new DeviceViewModel();
if (DeviceModelToAddInDesignTime != null)
deviceViewModel.AddDevice(DeviceModelToAddInDesignTime );
return deviceViewModel;
}
}
}
public class DesignTimeDeviceManager
{
private ObservableCollection<FakeDeviceModel> _DesignTimeDevices;
public ObservableCollection<FakeDeviceModel> DesignTimeDevices
{
get { return _DesignTimeDevices; }
set
{
if (_DesignTimeDevices != value)
{
_DesignTimeDevices = value;
ViewModelLocator.DeviceModelToAddInDesignTime = value.FirstOrDefault();
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
优点:
缺点:
它停止在另一个项目中工作,这本身就找不到原因.但是在重新编译和更改内容之后,设计师会给我一些异常,看起来像"无法施放"FakeDeviceModel"到"FakeDeviceModel""!! 我的猜测是Designer内部编译并使用这些类型的缓存(C:\ Users\firstname.lastname\AppData\Local\Microsoft\VisualStudio\12.0\Designer\ShadowCache).在我的解决方案中,根据事物的顺序,我创建了一个分配给静态实例的"FakeDeviceModel",并且"稍后",下次ViewModelLocator被要求提供ViewModel时,它会使用它实例.但是,如果在此期间他"重新编译"或使用不同的缓存,那么它并不是"完全"相同的类型.所以我不得不杀死设计师(XDescProc)并重新编译它才能工作,然后几分钟后再次失败.如果有人可以纠正我这将是伟大的.
d:DataContext和自定义转换器的多重绑定
之前的解决方案的问题是指向ViewModel和FakeDeviceModel是在不同的时刻创建(给出类型/强制转换问题)并解决它的事实,我需要同时创建它们
XAML:
<UserControl x:Class="MeltingControl.Views.DeviceTabView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d">
<d:UserControl.DataContext>
<MultiBinding Converter="{StaticResource DeviceDataContextConverter}">
<Binding Path="DeviceViewModelDesignTime" Source="{StaticResource ViewModelLocator}" />
<Binding>
<Binding.Source>
<device:FakeDeviceModel IsConnected="False"
IsBusy="False"
IsTrayOpen="False"
SerialNumber="DesignTimeSerie"
/>
</Binding.Source>
</Binding>
</MultiBinding>
</d:UserControl.DataContext>
public class DeviceDataContextConverter: IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values == null || values.Length == 0)
return null;
var vm = (DeviceViewModel)values[0];
if (values.Length >= 2)
{
var device = (IDeviceModel)values[1];
vm.AddDevice(device);
}
return vm;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Run Code Online (Sandbox Code Playgroud)
优点:-Works超级棒!当DataContext的绑定请求ViewModel时,我利用Converter来修改ViewModel并在返回之前注入我的设备
缺点:
我们失去了intelissense(使用ReSharper),因为他不知道转换器返回了什么类型
我可以用来解决这个问题的任何其他想法或修改?
小智 9
您可以创建一个IsConnected = true基于您的视图模式 ( FakeDeviceViewModel)返回的设计时 ViewModel,然后将其设置为设计时数据上下文:
d:DataContext="{d:DesignInstance viewModels:FakeDeviceViewModel,
IsDesignTimeCreatable=True}"
Run Code Online (Sandbox Code Playgroud)
viewModels:实际视图模型的 xaml 命名空间在哪里。
| 归档时间: |
|
| 查看次数: |
5755 次 |
| 最近记录: |