我有一个从ComboBox派生的自定义“DateRangeSelector”控件。这是一个带有以下过滤器的下拉控件:
1.今天
2.接下来的三天
3.接下来的三周时间
4.自定义范围(允许用户设置自定义日期范围)
现在这个“DateRangeSelector”控件被添加到另一个XAML(ActivityListMenuControlView.xaml)中:
<DateRangeSelector:DateRangeSelectorControl x:Name="DateRangeSelector"
Grid.Column="1"
Margin="10 0 0 0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
AutomationProperties.AutomationId="AID_TaskListDateRangeSelector"
DateRangeUpdatedCmd="{Binding Path=DateRangeSelectionUpdatedCommand}"
TodayDateUpdatedCmd="{Binding Path=TodayDateUpdatedCommand}"
FontSize="{StaticResource TaskListMenuFontSize}"
RangeOptions="{Binding Path=DateRangeSelectionOptions,
Mode=OneTime}"
SelectedDateRange="{Binding Path=SelectedRange,
Mode=TwoWay}"
Visibility="{Binding Path=ShowFilterOptions,
Converter={StaticResource boolToVisibility}}" />
从上面的代码可以看出,我在“DateRangeSelector”中创建了一个命令“TodayDateUpdatedCmd”,用于在系统日期发生变化时绑定到此控件中的“今天”过滤器并绑定到“ActivityListMenuControlViewModel”中的命令“TodayDateUpdatedCommand”。
更新日期的代码存在于“DateRangeSelector”本身的方法“SetDateValues”中。
我只是对如何从“ActivityListMenuControlViewModel”执行此方法感到困惑?
请帮忙。
更新: DateRangeSelector只是一个没有view / viewmodel的类。这是代码:
public class DateRangeSelectorControl : ComboBox, INotifyPropertyChanged
{
public static readonly DependencyProperty TodayDateUpdateCmdProperty = DependencyProperty.Register("TodayDateUpdatedCmd", typeof(ICommand), typeof(DateRangeSelectorControl),
new PropertyMetadata(null));
public ICommand TodayDateUpdatedCmd
{
get { return (ICommand)this.GetValue(TodayDateUpdateCmdProperty); }
set
{
this.SetValue(TodayDateUpdateCmdProperty, value);
}
}
/// <summary>
///
/// </summary>
private void SetDateValues()
{
DateTime todaysDate = DateTime.Now;
TodayText = Utility.GetStringFromResource("TodayLabel") + " (" + todaysDate.ToShortDateString() + ")";
NextThreeDaysText = Utility.GetStringFromResource("NextThreeDaysLabel") + " (" + todaysDate.ToShortDateString() + " - " + todaysDate.AddDays(3).ToShortDateString() + ")";
NextWeekText = Utility.GetStringFromResource("NextWeekLabel") + " (" + todaysDate.ToShortDateString() + " - " + todaysDate.AddDays(7).ToShortDateString() + ")";
SetCustomDateRangeText();
}
}
从上面的代码可以看出,我首先注册了一个依赖属性“TodayDateUpdateCmdProperty”和命令属性“TodayDateUpdatedCmd”,它在“ActivityListMenuControlView.xaml”中使用,如XAML片段中所示。此外,我需要在DateRangeSelector类中执行方法“SetDateValues”来更新今天的日期。 现在请帮我解决一下这个问题?
更新: 根据@GazTheDestroyer的建议,我对代码进行了更改,现在没有使用任何命令。但现在使用以下详细信息获取运行时XamlParseException:
“'匹配指定绑定约束的类型'VMS.Nexus.Client.Common.Controls.DateRangeSelector.DateRangeSelectorControl'上的构造函数的调用引发了异常。行号“45”和行位置“14”。“}
的InnerException: {“默认值类型与属性'TodayDate'的类型不匹配。”}
在ActivityListMenuControlView.xaml中抛出此异常,我创建了DateRangeSelector。 请帮忙
答案 0 :(得分:0)
特别是在编写WPF和MVVM时,开发人员通常会使用我们可以在视图模型中声明的delegate ICommand
形式。您可以在MSDN上WPF Apps With The Model-View-ViewModel Design Pattern页面的“中继命令逻辑”部分中找到常用RelayCommand
的实施详细信息。您可以在Stack Overflow上的How can I use the RelayCommand in wpf?问题中找到它的基本使用示例。
因此,您可以在视图模型中定义ICommand
个实例,并将数据绑定到控件。对于DateRangeSelector
,您只需声明类型为DependencyProperty
的{{1}},并将数据绑定到您的视图模型中的数据......可能是这样的:
ICommand
在您的视图模型中:
<DateRangeSelector:DateRangeSelectorControl TodayDateUpdatedCmd="{Binding Command}">
...
</DateRangeSelector:DateRangeSelectorControl>
更新&gt;&gt;&gt;
很简单地说,没有必要在WPF中的这个(或几乎任何)实例中扩展public ICommand Command
{
get { return new ActionCommand(action => DoSomething(),
canExecute => CanDoSomething(); }
}
类。有关无需执行此操作的原因的详细信息,请参阅MSDN上的Control Authoring Overview页面。
所以基本的想法是,你将功能从ComboBox
移到另一个类......一个视图模型类。然后,您可以将数据绑定到ComboBox
并提供功能。在WPF中,我们操纵数据,而不是 UIElement 。因此,而不是定义所有的过滤器&#39;在控件中,在代码中定义它们。
首先,您需要一个包含可用日期的集合属性:
ComboBox
接下来,您应该有一个public ObservableCollection<DateTime> AvailableDates
{
get { return availableDates; }
set { availableDates = value; NotifyPropertyChange("AvailableDates"); }
}
,其值代表每种过滤器类型。您可以在视图模型中添加此类型的属性,该属性可以控制每次更改时enum
中显示的项目:
ComboBox
...
public FilterType FilterType
{
get { return filterType; }
set
{
filterType = value;
NotifyPropertyChange("FilterType");
FillAvailableDatesDependantOnFilterType();
}
}
希望你现在有了更好的主意。
答案 1 :(得分:0)
命令应该由控件 触发,而不是用作到您似乎正在尝试的控件的通知机制。
如果您的控件需要对某些更改的变量做出反应,那么它应该公开DependencyProperty并对其进行更改。例如,在DateRangeSelectorControl
public static readonly new DependencyProperty TodaysDateProperty=
DependencyProperty.Register("TodaysDate", typeof(DateTime), typeof(DateRangeSelectorControl), new PropertyMetadata(null, TodaysDateChanged));
public new DateTime TodaysDate
{
get { return (DateTime)GetValue(TodaysDateProperty); }
set { SetValue(TodaysDateProperty, value); }
}
private static void TodaysDateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((DateRangeSelectorControl)d).TodaysDateChanged((DateTime)e.NewValue);
}
private void TodaysDateChanged(DateTime newDate)
{
//update your control here
}
然后,您的ViewModel可以简单地公开可以绑定到此DependencyProperty的TodaysDate
属性。