WPF:三个不同的网格绑定到Visibility-Property,有没有更有效的方法?



几个小时以来,我一直被以下问题所困扰:

我是WPF的新手,尤其是MVVM。我有三个不同的类(Car,Motorcycle,Truck)具有不同的性质。您可以在Combobox中选择车辆。下面是我的Car-Class的一个例子:

public class Car
{
public int Axes { get; set; }
public int Seats { get; set; }
public int Doors { get; set; }
public VehicleProperties.Car.Type Type { get; set; }
public int MaxWeight { get; set; }
public Fuel Fuel { get; set; }
public double ConsumptionPer100km { get; set; }
public bool Childseat { get; set; }
public string Brand { get; set; }
public string Model { get; set; }
public int FirstRegistration { get; set; }
public int Mileage { get; set; }
public Transmission Transmission { get; set; }
public int Power { get; set; }
public bool Tempomat { get; set; }
public SolidColorBrush Color { get; set; }
public int PollutionClass { get; set; }
public int EnvironmentalBadge { get; set; }
}

Motorcycle-Class:

public class Motorcycle
{
public string Brand { get; set; }
public string Model { get; set; }
public Fuel Fuel { get; set; }
public VehicleProperties.Motorcycle.Type Type { get; set; }
public int Power { get; set; }
public int FirstRegistration { get; set; }
public int Mileage { get; set; }
public DriveType DriveType { get; set; }
public Transmission Transmission { get; set; }
public int CubicCapacity { get; set; }
public int PollutionClass { get; set; }
public Brush Color { get; set; }
public int ConsumptionPer100km { get; set; }
}

Truck-Class:

public class Truck
{
public VehicleProperties.Truck.Type Type { get; set; }
public string Brand { get; set; }
public string Model { get; set; }
public int Mileage { get; set; }
public int Power { get; set; }
public Fuel Fuel { get; set; }
public Transmission Transmission { get; set; }
public int Axes { get; set; }
public int MaxWeight { get; set; }
public bool Tempomat { get; set; }
public SolidColorBrush Color { get; set; }
public int PollutionClass { get; set; }
public string WheelFormula { get; set; }
public int ConsumptionBadge { get; set; }
}

我必须创建一个窗口,您可以根据您选择的车辆创建新车辆。我首先考虑寻找类的属性,并在XAML中动态地检查DataTypeMarkup-Extension,但它不起作用,因为输出始终是string。最重要的是:即使我让它工作,我将如何动态绑定它们?

现在,我正在为每个类设计3个网格,将它们绑定到变量,并将Visibility-属性绑定到三个bools。有没有更有效的解决办法?我觉得这样做不对。

您应该使用DataTemplate为每种车辆类型创建不同的视图,例如Car。我们的想法是根据所选车辆数据类型显示DataTemplate。由于您将每个DataTemplate定义为隐式模板(没有x:Key指令),因此模板将自动应用(按数据类型)。

在下面的示例中,所选择的数据类型公开为绑定到ContentControlMainViewModel.NewVehicle属性。然后,ContentControl将自动应用适当的DataTemplateDataTemplateDataContextCar一样是当前的数据类型。这就是为什么你可以很容易地将模板的UI元素绑定到新实例。

每当您从ComboBox中选择一个类别时,MainViewModel将创建所选车辆类型的新空实例并将其分配给MainViewModel.NewVehicle属性。在你通过DataTemplate提供的UI编辑完新车之后,你就可以处理完成的MainViewModel.NewVehicle了。

接口IVehicleProvider旨在消除switch或多个if,以确定要创建的实际车辆类型。它是由IVehicle接口实现的,而每个车辆类型都必须实现这个接口。

解决方案的关键部分是使用DataTemplate(参见数据模板概述)为了创建三个个人编辑视图和IVehicleProvider消除开关类型。

MainWindow.xaml

<Window>
<Window.DataContext>
<MainViewModel />
</Window.DataContext>
<Window.Resources>
<DataTemplate DataType="{x:Type local:Car}">
<TextBlock Text="{Binding VehicleType}" Background="Green" />
</DataTemplate>
<DataTemplate DataType="{x:Type local:MotoryCycle}">
<TextBlock Text="{Binding VehicleType}" Background="Yellow" />
</DataTemplate>
<DataTemplate DataType="{x:Type local:Truck}">
<TextBlock Text="{Binding VehicleType}" Background="Red" />
</DataTemplate>
</Window.Resources>
<StackPanel>
<ComboBox ItemsSource="{Binding VehicleCategories}" 
DisplayMemberPath="VehicleType" 
SelectedItem="{Binding SelectedVehicleProvider}" />
<!-- Display the DataTemplate of the current type returned by NewVehicle -->
<ContentControl Content="{Binding NewVehicle}"  />
<StackPanel>
</Window>

MainViewModel.cs

class MainViewModel : INotifyPropertyChanged
{
public MainViewModel()
{
this.VehicleCategories = new List<IVehicle>
{
new Car(),
new Truck(),
new MotoryCycle()
};
}
private void OnSelectedvehicleCategoryChanged()
=> this.NewVehicle = this.SelectedVehicleCategoryProvider.CreateEmpty();
public List<IVehicle> VehicleCategories { get; }
// The new vehicle, ready for edit in a view provided by a DataTemplate.
private IVehicle newVehicle;
public IVehicle NewVehicle
{
get => this.newVehicle;
set
{
this.newVehicle = value;
OnPropertyChanged();
}
}
private IVehicleProvider selectedVehicleCategoryProvider;
public IVehicleProvider SelectedVehicleCategoryProvider
{
get => this.selectedVehicleCategory;
set
{
this.selectedVehicleCategory = value;
OnSelectedvehicleCategoryChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = "")
=> this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

VehicleType.cs

public enum VehicleType
{
Default = 0, 
Car, 
Truck, 
Motorcycle
}

IVehicle.cs

public interface IVehicle : IVehicleProvider
{
VehicleType VehicleType { get; }
}

IVehicleProvider.cs

public interface IVehicleProvider
{
IVehicle CreateEmpty();
}

Car.cs

public class Car : IVehicle
{
public VehicleType VehicleType => VehicleType.Car;
public IVehicle CreateEmpty() => new Car();
// Properties of Car
}

Truck.cs

public class Truck : IVehicle
{
public VehicleType VehicleType => VehicleType.Truck;
public IVehicle CreateEmpty() => new Truck();
// Properties of Truck
}

MotoryCycle.cs

public class MotoryCycle : IVehicle
{
public VehicleType VehicleType => VehicleType.Motorcycle;
public IVehicle CreateEmpty() => new MotoryCycle();
// Properties of MotoryCycle
}

相关内容

  • 没有找到相关文章

最新更新