问题描述
我正在尝试使用DevExpress SchedulerControl
在WPF中实现调度程序。我要做的是在创建新约会时,将新约会对象传递给视图模型以将其保存在数据库中。这是我的MainWindow
视图:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<dxsch:SchedulerControl x:Name="scheduler" ActiveViewType="WeekView" FirstDayOfWeek="Monday" Grid.Column="0">
<dxsch:SchedulerControl.OptionsWindows>
<dxsch:OptionsWindows AppointmentWindowType="{x:Type local:CrearTareaWindow}"/>
</dxsch:SchedulerControl.OptionsWindows>
<dxmvvm:Interaction.Behaviors>
<dxmvvm:EventToCommand EventName="AppointmentAdded" Command="{Binding SaveCommand}" />
<dxmvvm:EventToCommand Command="{Binding DeleteCommand}" EventName="AppointmentRemoved"/>
<dxmvvm:EventToCommand Command="{Binding EditCommand}" EventName="AppointmentEdited" />
</dxmvvm:Interaction.Behaviors>
<dxsch:SchedulerControl.DataSource>
<dxsch:DataSource AppointmentsSource="{Binding Tareas}">
<dxsch:DataSource.AppointmentMappings>
<dxsch:AppointmentMappings
Subject="nombre"
Description="descripcion"
Start="fechaInicio"
End="fechaFin">
<dxsch:CustomFieldMapping Mapping="custom" Name="custom" />
</dxsch:AppointmentMappings>
</dxsch:DataSource.AppointmentMappings>
</dxsch:DataSource>
</dxsch:SchedulerControl.DataSource>
</dxsch:SchedulerControl>
<dxe:DateNavigator Name="dateNavigator" Grid.Column="1" ShowTodayButton="False">
<dxe:DateNavigator.StyleSettings>
<dxsch:SchedulerDateNavigatorStyleSettings Scheduler="{Binding ElementName=scheduler}" />
</dxe:DateNavigator.StyleSettings>
</dxe:DateNavigator>
</Grid>
在这里,只要用户在调度程序中添加,删除或编辑约会,我就会调用3个命令。 我的ViewModel看起来像这样:
public class ViewModel: ViewModelBase {
public List < Tarea > Tareas {
get =>new List < Tarea > {
new Tarea {
nombre = "Cita con el doctor",descripcion = "Al PPL le duele la panza",fechaInicio = new DateTime(2020,10,1,12,0),fechaFin = new DateTime(2020,14,0)
}
};
}
public ICommand SaveCommand {
get {
return new RelayCommand(param =>Save(param));
}
}
void Save(object a) {
Console.Write(a);
}
public ICommand DeleteCommand {
get {
return new RelayCommand(param =>Delete(param));
}
}
void Delete(object a) {
Console.Write("");
}
public ICommand EditCommand {
get {
return new RelayCommand(param =>Edit(param));
}
}
void Edit(object a) {
Console.Write(a);
}
}
我正在使用自定义窗口来保存约会:
<StackPanel Margin="10">
<TextBlock FontWeight="Bold" Text="Nombre:"/>
<TextBox Text="{Binding Subject,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}"/>
<TextBlock FontWeight="Bold" Text="Descripción:"/>
<TextBox Text="{Binding Description,Mode=TwoWay}" Height="100"/>
<TextBlock FontWeight="Bold" Text="Fecha de Inicio:"/>
<DockPanel>
<dxe:DateEdit
x:Name="editorStartDate"
Width="150"
DockPanel.Dock="Left"
Style="{DynamicResource {dxscht:AppointmentWindowThemeKey ResourceKey=Editor_StartDate}}" />
<dxe:TextEdit
x:Name="editorStartTime"
Margin="4,0"
DockPanel.Dock="Left"
Style="{DynamicResource {dxscht:AppointmentWindowThemeKey ResourceKey=Editor_StartTime}}" />
</DockPanel>
<TextBlock FontWeight="Bold" Text="Fecha de fin:"/>
<DockPanel>
<dxe:DateEdit
x:Name="editorEndDate"
Width="150"
DockPanel.Dock="Left"
Style="{DynamicResource {dxscht:AppointmentWindowThemeKey ResourceKey=Editor_EndDate}}" />
<dxe:TextEdit
x:Name="editorEndTime"
Margin="4,0"
DockPanel.Dock="Left"
Style="{DynamicResource {dxscht:AppointmentWindowThemeKey ResourceKey=Editor_EndTime}}" />
</DockPanel>
<TextBlock FontWeight="Bold" Text="Custom:"/>
<TextBox Text="{Binding CustomFields.custom,Mode=TwoWay}"/>
<Grid Margin="0 10">
<Grid.Resources>
<Style TargetType="Button">
<Setter Property="Margin" Value="0 0 10 0"/>
</Style>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Button Grid.Column="0" Content="GUARDAR" Command="{Binding SaveAndCloseAppointmentCommand}"/>
<Button Grid.Column="1"
Content="BORRAR"
CommandParameter="{Binding ElementName=scheduler,Path=SelectedAppointments[0]}"
Command="{Binding RemoveAppointmentCommand}"/>
<Button Grid.Column="2" Content="CANCELAR" Command="{Binding CancelEditingCommand}"/>
</Grid>
</StackPanel>
问题是我没有找到一种方法来将创建,编辑或删除约会作为参数传递给命令。我在文档中没有发现任何相关内容。添加或删除时,命令被正确调用,但是找不到找到添加或删除约会对象的方法。我该怎么办?
解决方案更新
那个人的第一个解决方案运行良好,但第二个问题我遇到了问题。问题在于AppointmentItem没有DataContext属性,因此我必须对转换器进行一些更改:
protected override object Convert(object sender,AppointmentAddedEventArgs args) {
AppointmentItem appointmentItem = args.Appointments.FirstOrDefault();
Tarea tarea = new Tarea {
nombre = appointmentItem.Subject,descripcion = appointmentItem.Description,fechaInicio = appointmentItem.Start,fechaFin = appointmentItem.End,EtiquetaId = (int ? ) appointmentItem.LabelId,custom = appointmentItem.CustomFields["custom"].ToString()
};
return tarea;
}
在ViewModel中,采用如下所示的Appointment对象:
void Save(object a) {
Tarea tarea = (Tarea) a;
Console.Write(tarea);
}
有了这个,我在ViewModel中获得了添加的约会。
解决方法
每个事件都有一个关联的事件args类型。
这些事件参数每个都在Appointments
属性中包含一组受影响的约会。您可以通过设置PassEventArgsToCommand="True"
将这些事件参数自动作为CommandParameter
传递,例如:
<dxmvvm:EventToCommand EventName="AppointmentAdded"
Command="{Binding SaveCommand}"
PassEventArgsToCommand="True"/>
现在,您只需将传递给相应命令的对象转换为关联的事件args类型,然后访问Appointments
属性,例如对于更多约会:
void Save(object a) {
var args = (AppointmentAddedEventArgs)a;
var appointments = args.Appointments;
// ...do something with the appointments.
}
这解决了您的问题,但是不好,因为事件args是与用户界面相关的事件,不应将其传递到视图模型中。但是,有一个解决方案,因为您可以创建事件args转换器。请参见documentation中的示例。
您将为目标事件类型创建一个转换器。由于Appointments
集合包含AppointmentItem
个项目(它们是UI容器),因此您可以通过返回这样的Tarea
用Linq提取类型为SourceObject
的基础数据项目。>
public class AppointmentAddedEventArgsConverter : EventArgsConverterBase<AppointmentAddedEventArgs>
{
protected override object Convert(object sender,AppointmentAddedEventArgs args)
{
return args.Appointments.Select(ai => ai.SourceObject).Cast<Tarea>();
}
}
然后,您可以像这样在XAML中进行分配,它将自动将您的Tarea
项的枚举作为命令参数传递给命令。
<dxmvvm:EventToCommand EventName="AppointmentAdded"
Command="{Binding SaveCommand}">
<dxmvvm:EventToCommand.EventArgsConverter>
<local:AppointmentAddedEventArgsConverter />
</dxmvvm:EventToCommand.EventArgsConverter>
<dxmvvm:EventToCommand/>
在执行委托中,您可以将命令参数直接转换为提取的项目集合。
void Save(object a) {
var addedTareas = (IEnumerable<Tarea>)a;
// ...do something with the added items.
}