WPF 通知 MultiConverter 绑定的集合已更改
WPF Notify MultiConverter that the bound collection has changed
我是 wpf 的新手,我很难弄清楚如何通知多转换器它的绑定集合已更改。我尝试了几种解决方案,但没有任何效果。
我有一个带有多转换器的日历,允许我根据 2 个 Observablecollection 更改 calendardaybutton 背景。 (这很好,如果我在应用数据上下文之前手动将数据放入集合中,我可以看到日期是彩色的)。
当用户单击日历时,所选日期将添加到其中一个集合中。
我已经检查过,新日期已正确添加到集合中,但我没有看到日历上有任何变化(点击的 calendardaybutton 背景应该改变)。
这是我的 XAML:
<Window.Resources>
<local:DateConverter x:Key="dateConverter" />
<local:MyViewModel x:Key="myViewModel" />
</Window.Resources>
<Grid>
<Calendar x:Name="MyCal"
SelectionMode="MultipleRange"
SelectedDatesChanged="OnSelectedDatesChanged">
<Calendar.CalendarDayButtonStyle>
<Style TargetType="CalendarDayButton">
<Setter Property="Background" >
<Setter.Value>
<MultiBinding Converter="{StaticResource dateConverter}">
<Binding/>
<Binding Source="{StaticResource myViewModel}" Path="MyHolidayCollection" UpdateSourceTrigger="PropertyChanged"/>
<Binding Source="{StaticResource myViewModel}" Path="ShutDownDateCollection" UpdateSourceTrigger="PropertyChanged"/>
</MultiBinding>
</Setter.Value>
</Setter>
</Style>
</Calendar.CalendarDayButtonStyle>
</Calendar>
</Grid>`
我的 DataContext 是一个包含 2 个可观察集合的 ViewModel
public partial class MainWindow : Window
{
MyViewModel myViewModel;
public MainWindow()
{
myViewModel = new MyViewModel();
DataContext = myViewModel;
InitializeComponent();
}
private void OnSelectedDatesChanged(object sender, RoutedEventArgs e)
{
Calendar c = (Calendar)sender;
myViewModel.AssignDate(c.SelectedDate);
}
}
这是我的ViewModel(继承自ViewModelBase,实现了INotifyPropertyChanged)
public class MyViewModel:ViewModelBase
{
private ObservableCollection<DateTime?> _holidayDateCollection;
public ObservableCollection<DateTime?> HolidayDateCollection
{
get { return _holidayDateCollection; }
set
{
_holidayDateCollection = value;
OnPropertyChanged("HolidayDateCollection");
}
}
private ObservableCollection<DateTime?> _shutDownDateCollection;
public ObservableCollection<DateTime?> ShutDownDateCollection
{
get { return _holidayDateCollection; }
set
{
_holidayDateCollection = value;
OnPropertyChanged("ShutDownDateCollection");
}
}
public MyViewModel()
{
HolidayDateCollection = new ObservableCollection<DateTime?>();
ShutDownDateCollection = new ObservableCollection<DateTime?>();
}
public void AssignDate(DateTime? date)
{
HolidayDateCollection.Add(date);
}
这是我的多转换器
public class DateConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
SolidColorBrush s = new SolidColorBrush(Colors.LightBlue);
SolidColorBrush s1 = new SolidColorBrush(Colors.Yellow);
SolidColorBrush s2 = new SolidColorBrush(Colors.Red);
if (((ObservableCollection<DateTime?>)values[1]).Contains((DateTime?)values[0])) { return s1; }
if (((ObservableCollection<DateTime?>)values[2]).Contains((DateTime?)values[0])) { return s2; }
return s;//normal day
}
public object[] ConvertBack(object value, Type[] targetTypes,
object parameter, System.Globalization.CultureInfo culture)
{
throw new NotSupportedException("Cannot convert back");
}
}
我尝试了很多解决方案(我删除了这些解决方案以清除此处的代码)但似乎没有任何效果。
任何帮助或建议将不胜感激,我已经被困了好几天了。谢谢。
您引用了两个完全不同的 ViewModel
实例,这就是您遇到此问题的原因。
实例 1:(在 xaml 内)
<Window.Resources>
<local:DateConverter x:Key="dateConverter" />
<local:MyViewModel x:Key="myViewModel" />
</Window.Resources>
实例 2:(在您的代码隐藏文件中)
myViewModel = new MyViewModel();
DataContext = myViewModel;
要解决此问题,请从任一实例更改 MyViewModel
实例。例如,删除表单 xaml 后,您的代码将如下所示:
<Window.Resources>
<local:DateConverter x:Key="dateConverter" />
</Window.Resources>
<Grid>
<Calendar x:Name="MyCal"
SelectionMode="MultipleRange"
SelectedDatesChanged="OnSelectedDatesChanged">
<Calendar.CalendarDayButtonStyle>
<Style TargetType="CalendarDayButton">
<Setter Property="Background" >
<Setter.Value>
<MultiBinding Converter="{StaticResource dateConverter}">
<Binding />
<Binding RelativeSource="{RelativeSource AncestorType=Window, Mode=FindAncestor}" Path="DataContext.HolidayDateCollection" UpdateSourceTrigger="PropertyChanged"/>
<Binding RelativeSource="{RelativeSource AncestorType=Window, Mode=FindAncestor}" Path="DataContext.ShutDownDateCollection" UpdateSourceTrigger="PropertyChanged"/>
</MultiBinding>
</Setter.Value>
</Setter>
</Style>
</Calendar.CalendarDayButtonStyle>
</Calendar>
</Grid>
我是 wpf 的新手,我很难弄清楚如何通知多转换器它的绑定集合已更改。我尝试了几种解决方案,但没有任何效果。
我有一个带有多转换器的日历,允许我根据 2 个 Observablecollection 更改 calendardaybutton 背景。 (这很好,如果我在应用数据上下文之前手动将数据放入集合中,我可以看到日期是彩色的)。
当用户单击日历时,所选日期将添加到其中一个集合中。
我已经检查过,新日期已正确添加到集合中,但我没有看到日历上有任何变化(点击的 calendardaybutton 背景应该改变)。
这是我的 XAML:
<Window.Resources>
<local:DateConverter x:Key="dateConverter" />
<local:MyViewModel x:Key="myViewModel" />
</Window.Resources>
<Grid>
<Calendar x:Name="MyCal"
SelectionMode="MultipleRange"
SelectedDatesChanged="OnSelectedDatesChanged">
<Calendar.CalendarDayButtonStyle>
<Style TargetType="CalendarDayButton">
<Setter Property="Background" >
<Setter.Value>
<MultiBinding Converter="{StaticResource dateConverter}">
<Binding/>
<Binding Source="{StaticResource myViewModel}" Path="MyHolidayCollection" UpdateSourceTrigger="PropertyChanged"/>
<Binding Source="{StaticResource myViewModel}" Path="ShutDownDateCollection" UpdateSourceTrigger="PropertyChanged"/>
</MultiBinding>
</Setter.Value>
</Setter>
</Style>
</Calendar.CalendarDayButtonStyle>
</Calendar>
</Grid>`
我的 DataContext 是一个包含 2 个可观察集合的 ViewModel
public partial class MainWindow : Window
{
MyViewModel myViewModel;
public MainWindow()
{
myViewModel = new MyViewModel();
DataContext = myViewModel;
InitializeComponent();
}
private void OnSelectedDatesChanged(object sender, RoutedEventArgs e)
{
Calendar c = (Calendar)sender;
myViewModel.AssignDate(c.SelectedDate);
}
}
这是我的ViewModel(继承自ViewModelBase,实现了INotifyPropertyChanged)
public class MyViewModel:ViewModelBase
{
private ObservableCollection<DateTime?> _holidayDateCollection;
public ObservableCollection<DateTime?> HolidayDateCollection
{
get { return _holidayDateCollection; }
set
{
_holidayDateCollection = value;
OnPropertyChanged("HolidayDateCollection");
}
}
private ObservableCollection<DateTime?> _shutDownDateCollection;
public ObservableCollection<DateTime?> ShutDownDateCollection
{
get { return _holidayDateCollection; }
set
{
_holidayDateCollection = value;
OnPropertyChanged("ShutDownDateCollection");
}
}
public MyViewModel()
{
HolidayDateCollection = new ObservableCollection<DateTime?>();
ShutDownDateCollection = new ObservableCollection<DateTime?>();
}
public void AssignDate(DateTime? date)
{
HolidayDateCollection.Add(date);
}
这是我的多转换器
public class DateConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
SolidColorBrush s = new SolidColorBrush(Colors.LightBlue);
SolidColorBrush s1 = new SolidColorBrush(Colors.Yellow);
SolidColorBrush s2 = new SolidColorBrush(Colors.Red);
if (((ObservableCollection<DateTime?>)values[1]).Contains((DateTime?)values[0])) { return s1; }
if (((ObservableCollection<DateTime?>)values[2]).Contains((DateTime?)values[0])) { return s2; }
return s;//normal day
}
public object[] ConvertBack(object value, Type[] targetTypes,
object parameter, System.Globalization.CultureInfo culture)
{
throw new NotSupportedException("Cannot convert back");
}
}
我尝试了很多解决方案(我删除了这些解决方案以清除此处的代码)但似乎没有任何效果。
任何帮助或建议将不胜感激,我已经被困了好几天了。谢谢。
您引用了两个完全不同的 ViewModel
实例,这就是您遇到此问题的原因。
实例 1:(在 xaml 内)
<Window.Resources>
<local:DateConverter x:Key="dateConverter" />
<local:MyViewModel x:Key="myViewModel" />
</Window.Resources>
实例 2:(在您的代码隐藏文件中)
myViewModel = new MyViewModel();
DataContext = myViewModel;
要解决此问题,请从任一实例更改 MyViewModel
实例。例如,删除表单 xaml 后,您的代码将如下所示:
<Window.Resources>
<local:DateConverter x:Key="dateConverter" />
</Window.Resources>
<Grid>
<Calendar x:Name="MyCal"
SelectionMode="MultipleRange"
SelectedDatesChanged="OnSelectedDatesChanged">
<Calendar.CalendarDayButtonStyle>
<Style TargetType="CalendarDayButton">
<Setter Property="Background" >
<Setter.Value>
<MultiBinding Converter="{StaticResource dateConverter}">
<Binding />
<Binding RelativeSource="{RelativeSource AncestorType=Window, Mode=FindAncestor}" Path="DataContext.HolidayDateCollection" UpdateSourceTrigger="PropertyChanged"/>
<Binding RelativeSource="{RelativeSource AncestorType=Window, Mode=FindAncestor}" Path="DataContext.ShutDownDateCollection" UpdateSourceTrigger="PropertyChanged"/>
</MultiBinding>
</Setter.Value>
</Setter>
</Style>
</Calendar.CalendarDayButtonStyle>
</Calendar>
</Grid>