OCLMEditorModel // The main model
OCLMEditorModelData // main data read from XML file (using XMLSerializer)
List<Meeting> Meetings // List of Meeting objects
除此之外,会议对象包括:
Meeting
Date
SpecialEvent
SpecialEvent 的位置是:
SpecialEvent
Description
Location
Type
OCLMEditorViewModel // This inherits from INotifyPropertyChanged
ObservableCollection Meetings // Using the OCLMEditorModel.OCLMEditorModelData.Meetings list as a source
Meeting // The current meeting object
_Model = new OCLMEditorModel();
_MeetingsList = new ObservableCollection<Data.MeetingInfo.Meeting>(_Model.Meetings);
_Meeting = _Model.MeetingForThisWeek(); // Starts us off correctly (right item in the Meetings list)
这包含会议集合的ComboBox:
<ComboBox x:Name="comboMeetingWeek" ItemsSource="{Binding Meetings}"
SelectedItem="{Binding Meeting, UpdateSourceTrigger=PropertyChanged}">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Source="Images/Bell.png" Margin="0,0,5,0"
Visibility="{Binding IsSpecialEvent, Converter={StaticResource BoolToHiddenConverter}}" Stretch="None"/>
<TextBlock Text="{Binding DateMeetingAsText}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
所以源是ObservableCollection。并且SelectedItem必须:
public Data.MeetingInfo.Meeting Meeting
{
get { return _Meeting; }
set
{
// Has the existing meeting object changed at all?
if(_Meeting != null && _Meeting.IsDirty)
{
// Yes, so save it
_Model.Serialize();
_Meeting.MarkClean();
}
// Now we can update to new value
if (value != null)
{
_Meeting = value;
OnPropertyChanged("Meeting");
}
}
}
private Data.MeetingInfo.Meeting _Meeting;
据我所知,这是对MVVM的正确使用。但现在我想更进一步。我将Image
用于ContextMenu
:
<Image Grid.Column="1" HorizontalAlignment="Right" Source="Images\event_time.png" Margin="2">
<Image.ContextMenu>
<ContextMenu>
<MenuItem Header="Set Special Event" Command="{Binding SetSpecialEventCommand, Mode=OneWay}">
<MenuItem.Style>
<Style TargetType="MenuItem">
<Setter Property="IsEnabled" Value="True"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Meeting.IsSpecialEvent}" Value="True">
<Setter Property="IsEnabled" Value="False"/>
</DataTrigger>
</Style.Triggers>
</Style>
</MenuItem.Style>
</MenuItem>
<MenuItem Header="Remove Special Event">
<MenuItem.Style>
<Style TargetType="MenuItem">
<Setter Property="IsEnabled" Value="False"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Meeting.IsSpecialEvent}" Value="True">
<Setter Property="IsEnabled" Value="True"/>
</DataTrigger>
</Style.Triggers>
</Style>
</MenuItem.Style>
</MenuItem>
</ContextMenu>
</Image.ContextMenu>
</Image>
问题...我们在ComboBox当前选择了Meeting对象...
如果我右键单击并选择设置特殊事件,我将显示一个弹出窗口。这是我有点困惑的地方。我知道我必须使用&#34; UpdateSourceTrigger =明确&#34;在弹出窗口内,然后在OK按钮中执行更新(特殊事件描述,位置,类型)。
我的弹出窗口有问题。 XAML:
<Window x:Class="OCLMEditor.SpecialEventWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:OCLMEditor"
mc:Ignorable="d"
Title="SpecialEventWindow" Height="300" Width="300">
<Grid>
<TextBox x:Name="textDescription" HorizontalAlignment="Left" Height="23" Margin="38,49,0,0" TextWrapping="Wrap"/>
</Grid>
</Window>
_SetSpecialEventCommand = new DelegateCommand<string>(
(s) =>
{
SpecialEventWindow windowEvent = new SpecialEventWindow();
windowEvent.DataContext = _Meeting.SpecialEvent;
windowEvent.ShowDialog();
},
(s) => true);
然而,在弹出窗口的XAML编辑器中,它认为它没有DataContext。所以它不允许我将文本框绑定到其中一个属性。
我不确定提出的评论,因为他们显然错过了设置DataContext的代码。但很容易错过。它就在那里。 :)
_SetSpecialEventCommand = new DelegateCommand<string>(
(s) =>
{
SpecialEventWindow windowEvent = new SpecialEventWindow();
windowEvent.DataContext = _Meeting.SpecialEvent;
windowEvent.ShowDialog();
},
(s) => true);
工作。但我得到的是,当我在代码中设置datacontext时,XAML编辑器似乎并不知道它。因此,当我点击控件并转到绑定时......它不会显示出来。
我的主窗口有:
因此它显示了活动数据上下文,我可以使用IDE来浏览绑定。但不是在这个弹出窗口。我必须在代码编辑器中手动完成所有操作。
答案 0 :(得分:2)
您在运行时给弹出窗口drives
,但不是在设计时。 IDE不够智能,无法通过分析代码来弄清楚您希望它做什么。
你的主窗口在设计时有一个DataContext的原因是因为你在XAML 中给它一个声明性的,这不需要任何深入的洞察IDE的部分来计算你的欲望是什么;你只是设置一个属性,在设计时发生 的事情:
DataContext
使用<Window.DataContext>
<local:OCLMEditorViewModel />
</Window.DataContext>
实例初始化主窗口的DataContext
属性,这是您在“新建”按钮旁边的属性中看到的属性。你没有在弹出窗口中看到它,因为你没有在弹出窗口的XAML中那样做。那是因为您在运行时使用特定的预先存在的OCLMEditorViewModel
实例设置其DataContext
。
有两种方法可以在这里得到你想要的东西:首先,“正确”的方式,即使用SpecialEvent
可忽略的属性:
d:DataContext
这需要<Window
...
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance Type=local:SpecialEvent, IsDesignTimeCreatable=True}"
...
>
拥有默认构造函数。它可以在detects that it's been instantiated at design time(或不是)时进行特殊的“模拟数据”初始化。
更简单(但不是很好),在您的情况下,您可以像在主窗口中那样实例化它:
SpecialEvent
那将在设计时为您打字<Window.DataContext>
<local:SpecialEvent />
</Window.DataContext>
。在运行时,显示对话框的命令将使用从DataContext
获取的特定实例替换该垃圾实例,因为所有XAML内容都是在_Meeting.SpecialEvent
的构造函数完成时完成的。