The Model
OCLMEditorModel // The main model
OCLMEditorModelData // main data read from XML file (using XMLSerializer)
List<Meeting> Meetings // List of Meeting objects
Amongst other things, the Meeting object includes:
Meeting
Date
SpecialEvent
Where SpecialEvent is:
SpecialEvent
Description
Location
Type
The ModelView
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)
The View
This contains a ComboBox of the Meetings collection:
<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>
So the source is the ObservableCollection. And the SelectedItem is bound to:
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;
As far as I am aware this is a correct use of MVVM. But now I want to go a step further. I have this Image
that I am going to use for a 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>
The question ... We have the Meeting object that is currently selected in the ComboBox ...
If I right-click and choose Set Special Event I wan tto show a popup window. This is where I geta bit confused. I understand that I must use "UpdateSourceTrigger=Explicit" inside the popup window and then in the OK button perform the update (special event description, location, type).
I have a problem with the popup window. 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);
Yet, in the XAML editor for the popup window it thinks it has no DataContext. So it will not let me bind the text box to one of the properties.
Update
I am not sure about the comment that was raised as they clearly missed my code that sets the DataContext. But it is easy to miss. It is there. :)
_SetSpecialEventCommand = new DelegateCommand<string>(
(s) =>
{
SpecialEventWindow windowEvent = new SpecialEventWindow();
windowEvent.DataContext = _Meeting.SpecialEvent;
windowEvent.ShowDialog();
},
(s) => true);
It does work. But what I am getting at is that when I set the datacontext in code, the XAML editor doesn't seem to know about it. So when I click on controls and go to bind... it doesn't show up.
My MainWindow has:
So it shows the active data context and I can use the IDE to navigate through bindings. But not on this popup window. I have to do it all manually in the code editor.