繁体   English   中英

如何使用 WPF 和 MVVM 在 DevExpress Scheduler 控件上获取保存的约会?

[英]How to get the saved Appointment on a DevExpress Scheduler control using WPF and MVVM?

我正在尝试使用 DevExpress SchedulerControl在 WPF 中实现调度SchedulerControl 我想要做的是在创建新约会的那一刻,将新约会对象传递给视图模型以将其保存在数据库中。 这是我的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, 0),
        fechaFin = new DateTime(2020, 10, 1, 14, 0, 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, UpdateSourceTrigger=PropertyChanged, 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,0,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,0,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 中获得了添加的约会。

每个事件都有一个关联的事件参数类型。

这些事件参数每个都包含Appointments属性中受影响约会的集合。 您可以通过设置PassEventArgsToCommand="True"自动将这些事件参数作为CommandParameter传递,例如:

<dxmvvm:EventToCommand EventName="AppointmentAdded"
                       Command="{Binding SaveCommand}"
                       PassEventArgsToCommand="True"/>

现在,您可以将传递给相应命令的对象强制转换为关联的事件参数类型并访问Appointments属性,例如添加约会:

void Save(object a) {
   var args = (AppointmentAddedEventArgs)a;
   var appointments = args.Appointments;
   
   // ...do something with the appointments.
}

这解决了您的问题,但并不好,因为事件参数与用户界面相关,不应传递到视图模型中。 但是,有一个解决方案,因为您可以创建一个事件参数转换器。 请参阅文档中的示例。

您将为目标事件类型创建一个转换器。 由于Appointments集合包含AppointmentItem项,它们是 UI 容器,您可以使用 Linq 通过像这样返回它们的SourceObject来提取类型为Tarea基础数据项。

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.
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM