I'm a relative beginner with WPF so please bear with me. I have a simple app that converts farenheit values to celcius and vice versa. I thought I would have a play with refactoring this to MVVM so I moved everything from my code-behind to a separate class and then set the dataContext programmatically. However I'm getting a lot of ..'does not exist in context errors'. Where am I going wrong? Thanks
XAML
<Window x:Class="FarenheitCelciusConverter.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Temperature Converter" Height="500" Width="500"
xmlns:local="clr-namespace:FarenheitCelciusConverter">
<Grid HorizontalAlignment="Left" VerticalAlignment="Top" Height="473" Width="488">
<Label Height="28" HorizontalAlignment="Left" Margin="10,10,0,0" Name="lblF" VerticalAlignment="Top" Width="64" FontWeight="Bold">Farenheit</Label>
<Label Height="28" HorizontalAlignment="Left" Margin="10,42,0,0" Name="lblC" VerticalAlignment="Top" Width="64" FontWeight="Bold">Celcius</Label>
<TextBox Height="23" Margin="94,10,112,0" Name="tbFaren" VerticalAlignment="Top" Width="72" HorizontalAlignment="Left" />
<TextBox Height="23" Margin="94,42,112,0" Name="tbCelcius" VerticalAlignment="Top" Width="72" HorizontalAlignment="Left" />
<Button Margin="94,76,109,0" Name="btnConvert" Click="btnConvert_Click" Height="23" VerticalAlignment="Top" HorizontalContentAlignment="Center" Width="72" HorizontalAlignment="Left">Convert</Button>
<Image Name="image1" Stretch="Fill" Margin="94,112,240,228">
<Image.Source>
<BitmapImage DecodePixelWidth="200" UriSource="C:\Users\Winston\Pictures\thermometer.jpg"/>
</Image.Source>
</Image>
<TextBlock FontWeight="Bold" Height="21" Margin="195,12,173,0" Name="tblCelci" VerticalAlignment="Top" /><TextBlock FontWeight="Bold" Height="21" Margin="195,44,0,0" Name="tblFarenh" VerticalAlignment="Top" HorizontalAlignment="Left" Width="120" /><TextBlock FontWeight="Bold" Height="21" Margin="195,78,15,0" Name="tblCex" VerticalAlignment="Top" Foreground="Red" />
</Grid>
</Window>
Code behind
namespace FarenheitCelciusConverter
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
DataContext = new ConverterViewModel();
}
}
}
View Model
namespace FarenheitCelciusConverter
{
public class ConverterViewModel
{
private void btnConvert_Click(object sender, RoutedEventArgs e)
{
tblCex.Text = "";
try
{
if (tbCelcius.Text.Length != 0)
{
double celcius = Double.Parse(tbCelcius.Text);
if (celcius < 99999.0 && celcius > -99999.0)
{
tblFarenh.Text = Math.Round(1.8 * celcius + 32.0) + " F";
}
else
{
throw new OverflowException("Number limit exceeded!");
}
}
if (tbFaren.Text.Length != 0)
{
double farenh = Double.Parse(tbFaren.Text);
if (farenh < 99999.0 && farenh > -99999.0)
{
tblCelci.Text = Math.Round(0.555 * (farenh - 32.0)) + " C";
}
else
{
throw new OverflowException("Number limit exceeded!");
}
}
}
catch (Exception ex)
{
tblCex.Text = ex.Message;
}
}
}
}
When using MVVM data is passed back and forth from the View (Window1) and the ViewModel through Databinding. So each of your textboxes should be databound to a public property in your Viewmodel:
<TextBox Height="23" Margin="94,10,112,0" Name="tbFaren" VerticalAlignment="Top" Width="72" HorizontalAlignment="Left" Text="{Binding FahrenText}"/>
And your ViewModel will take the values in the properties, do something with them, and set the properties bound to the appropriate textboxes.
In this way, the Viewmodel is performing the logic and the View is interpreting the output according to the rules that you are giving it. Later on, you can change the rules in the View without messing with the ViewModel whereas using the codebehind often you have to explicitly set View settings alongside the program logic.
Also, be sure to implement iNotifyPropertyChanged on your ViewModel , otherwise the UI wont know when the databound property values have changed and it wont update. Check out this post for an example.
Also here is the MSDN article on Databinding in WPF.
Related
I am creating a simple currency converter app in WPF C#. I need to convert the currency USD to Indian rupees or Srilankan rupees, but couldn't process the output.
Furthermore, I have done the design and code when I ran the application output not displayed and error also not displayed what was a problem I don't know. What I tried so far I attached the code below, please have a look.
WPF design
<Grid>
<Label Content="Amount :"
Grid.Row="0"
Grid.Column="0"/>
<TextBox x:Name="TextBoxAmount"
Grid.Row="0"
Grid.Column="1"/>
<Label Content="From :"
Grid.Row="2"
Grid.Column="0"/>
<ComboBox Name="CboFrom" HorizontalAlignment="Left" VerticalAlignment="Top" Width="100" Height="25" Grid.Row="2"
Grid.Column="1">
<ComboBoxItem Content="USD"/>
</ComboBox>
<Label Content="To :"
Grid.Row="4"
Grid.Column="0"/>
<ComboBox Name="CboTo" HorizontalAlignment="Left" VerticalAlignment="Top"
Width="100" Height="25" Grid.Row="4"
Grid.Column="1">
<ComboBoxItem Content="Srilankan Rupees"/>
<ComboBoxItem Content="Indian Rupees"/>
</ComboBox>
<Label Content="Total :"
Grid.Row="6"
Grid.Column="0"/>
<TextBox
x:Name="TextBoxTotal"
Grid.Row="6"
Grid.Column="1"/>
</Grid>
<StackPanel
Grid.Row="8"
Grid.ColumnSpan="2"
Orientation="Horizontal">
<Button
Width="60"
Height="30"
Content="Convert"
x:Name="ButtonConvert"
Margin="10 0 10 0"
Click="ButtonConvert_Click" Background="#FF04097E" Foreground="White"/>
</StackPanel>
C# Code
private void ButtonConvert_Click(object sender, RoutedEventArgs e)
{
double tot;
double amount = double.Parse(TextBoxAmount.Text);
if (CboFrom.SelectedItem == "USD" && CboTo.SelectedItem == "Srilankan Rupees")
{
tot = amount * 179.50;
TextBoxTotal.Text = tot.ToString();
}
else if (CboFrom.SelectedItem == "USD" && CboTo.SelectedItem == "Indian Rupees")
{
tot = amount * 70;
TextBoxTotal.Text = tot.ToString();
}
}
CboFrom.SelectedItem is not a string, it's a ComboBoxItem.
What you want to compare is ((ComboBoxItem)CboFrom.SelectedItem).Content.ToString().
Which gives you:
if (((ComboBoxItem)CboFrom.SelectedItem).Content.ToString() == "USD" && ((ComboBoxItem)CboTo.SelectedItem).Content.ToString() == "Srilankan Rupees")
Whilst that will work, it is definitely hacky and bad design. I advise you look into EldHasp's suggestions to improve your design.
You set a collection of UI elements in the ComboBox - ComboBoxItem. Therefore, you select a UI element. And it will not work to compare it with the value of the data.
According to the application logic, you need to set the data collection in the ComboBox source so that you can select this data.
In its simplest form, it would be something like this:
public static class SomeHelper
{
public static ReadOnlyCollection CurrencyСodes {get;} = Array.AsReadOnly(new string[] {"USD"});
public static ReadOnlyCollection CurrencyNames {get;} = Array.AsReadOnly(new string[] {"Srilankan Rupees", "Indian Rupees"});
}
<ComboBox x:Name="CboFrom" HorizontalAlignment="Left" VerticalAlignment="Top" Width="100" Height="25"
Grid.Row="2" Grid.Column="1"
ItemsSource="{x:Static local:SomeHelper.CurrencyСodes}"/>
<ComboBox x:Name="CboTo" HorizontalAlignment="Left" VerticalAlignment="Top" Width="100" Height="25"
Grid.Row="4" Grid.Column="1"
ItemsSource="{x:Static local:SomeHelper.CurrencyNames}"/>
private void ButtonConvert_Click(object sender, RoutedEventArgs e)
{
double tot;
double amount = double.Parse(TextBoxAmount.Text);
if (CboFrom.SelectedItem == SomeHelper.CurrencyСodes[0])
{
if (CboTo.SelectedItem == SomeHelper.CurrencyNames[0])
{
tot = amount * 179.50;
TextBoxTotal.Text = tot.ToString();
}
else if (CboTo.SelectedItem == SomeHelper.CurrencyNames[1])
{
tot = amount * 70;
TextBoxTotal.Text = tot.ToString();
}
}
}
P.S. But I would recommend that you implement a normal WPF-typical ViewModel. This will greatly simplify the code, make it easier to read and understand. Reduce the likelihood of various errors.
I just want to make things clear about databinding, so I try things. I want to change contents of some dependency objects dinamically using with binding methods.
Basically what I try to accomplish is writing something in datePickerApp; and show it in richTextBoxComplaint dinamically. (with Button_CLick_2)
It kinda works for the first time I call the property; but for the second time it is not get updated
When I debug the code, beside the first click, I see that it sets the corresponding value but not going inside of the object and calling get for the particular value that I want to see.
I tried to add DataContext=this; to my main function and UpdateSourceTrigger values to my binding objects but still doesn't work.
Here is my XAML code:
<GroupBox Header="Randevu Paneli" Height="233" VerticalAlignment="Bottom" HorizontalAlignment="Left" Width="208" DataContext="{Binding Appointment, Mode=TwoWay, ElementName=ViewRoot}">
<StackPanel HorizontalAlignment="Stretch" Height ="210" VerticalAlignment="Bottom" Orientation="Horizontal">
<StackPanel Width="55" Height="190" VerticalAlignment="Bottom" Orientation="Vertical">
<Label Height="24" HorizontalAlignment="Right">Branş:</Label>
<Label Height="24" HorizontalAlignment="Right">Doktor:</Label>
<Label Height="24" HorizontalAlignment="Right">Tarih:</Label>
<Label Height="24" HorizontalAlignment="Right">Saat:</Label>
<Label Height="24" HorizontalAlignment="Right">Şikayet:</Label>
<StackPanel Height="45"></StackPanel>
<Button Height="25" Click="Button_Click" VerticalAlignment="Bottom">Çıkış</Button>
</StackPanel>
<StackPanel Height="185" Width="130" Orientation="Vertical" VerticalAlignment="Bottom">
<ComboBox x:Name="comboBranch" Width="115" SelectionChanged="ComboBox_SelectionChanged"></ComboBox>
<ComboBox x:Name="comboDr" Width="115"></ComboBox>
<DatePicker x:Name="datePickerApp" Width="115" Text="{Binding Date}"></DatePicker>
<ComboBox x:Name="timePickerApp" Width="115" SelectedItem="{Binding Hour}"></ComboBox>
<RichTextBox x:Name="richTextBoxComplaint" Width="115" Height="44">
<FlowDocument>
<Paragraph>
<Run Text="{Binding Date}"></Run>
</Paragraph>
</FlowDocument>
</RichTextBox>
<Button Width="115" Height="25" Click="Button_Click_2">Randevu Talep Et</Button>
<Button Width="115" Height="25" Click="Button_Click_1">Bilgilerini Düzenle</Button>
</StackPanel>
</StackPanel>
</GroupBox>
And my .cs with corresponding areas:
Appointments _appointment;
public Appointments Appointment
{
get
{
return _appointment;
}
set
{
_appointment = value;
OnPropertyChanged("Appointment");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChangedEventArgs e = new PropertyChangedEventArgs(propertyName);
PropertyChanged(this, e);
}
}
private void Button_Click_2(object sender, RoutedEventArgs e)
{
app.Date = datePickerApp.Text;
Appointment = app;
}
As I said it works for the first click but that's it. It shows the old value for other tries. Somehow get doesnt work properly; it works for the object itself but not for the 'Date' variable in particular.
When I debug the code in first click, I see that it goes to 'Appointments' class and call get 'Date' in particular. But it doesnt work the same way for other clicks.
What could I missing?
i stumbled across a curiosity in WPF which i couldn't explain myself an which i couldn't solve by searching online. So i hope one of you is able to give me a hint to understand my mistake.
Problem: The wpf-window dimensions seems to be 16 units bigger than the screen-resolution. The 16 pixels/units are independent from dimension (windowwidth, windowheight) and screen resolution.
The Problem is shown in the following Application:
XAML:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="250" Width="350">
<DockPanel Margin="10,10,0,0">
<DockPanel Width="152" DockPanel.Dock="Top" VerticalAlignment="Top" HorizontalAlignment="Left">
<TextBlock x:Name="displayHeight" HorizontalAlignment="Left" Margin="0,5,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="60"/>
<Label Content="Displayheight" HorizontalAlignment="Left" VerticalAlignment="Top" Height="30"/>
</DockPanel>
<DockPanel Width="148" DockPanel.Dock="Top" VerticalAlignment="Top" HorizontalAlignment="Left">
<TextBlock x:Name="displayWidth" HorizontalAlignment="Left" Margin="0,5,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="60"/>
<Label Content="Displaywidth" HorizontalAlignment="Left" VerticalAlignment="Top" Height="30"/>
</DockPanel>
<DockPanel Width="162" DockPanel.Dock="Top" VerticalAlignment="Top" HorizontalAlignment="Left">
<TextBlock HorizontalAlignment="Left" Margin="0,5,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Text="{Binding ActualHeight, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" Width="60"/>
<Label Content="Windowheight" HorizontalAlignment="Left" VerticalAlignment="Top" Height="30" Width="92"/>
</DockPanel>
<DockPanel Width="153" DockPanel.Dock="Top" VerticalAlignment="Top" HorizontalAlignment="Left">
<TextBlock HorizontalAlignment="Left" Margin="0,5,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Text="{Binding ActualWidth, Mode=OneWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" Width="60"/>
<Label Content="Windowwidth" HorizontalAlignment="Left" VerticalAlignment="Top" Height="30"/>
</DockPanel>
</DockPanel>
</Window>
C#:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Windows;
using System.Windows.Forms;
using System.Drawing;
namespace WpfApplication1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
IntPtr ownerHandle = Process.GetCurrentProcess().MainWindowHandle;
WpfScreen currentScreen = WpfScreen.GetScreenFrom(ownerHandle);
Rect workingArea = currentScreen.WorkingArea;
this.displayHeight.Text = workingArea.Height.ToString();
this.displayWidth.Text = workingArea.Width.ToString();
}
}
public class WpfScreen
{
public static WpfScreen GetScreenFrom(IntPtr windowIntPTR)
{
Screen screen = System.Windows.Forms.Screen.FromHandle(windowIntPTR);
WpfScreen wpfScreen = new WpfScreen(screen);
return wpfScreen;
}
private readonly Screen screen;
internal WpfScreen(System.Windows.Forms.Screen screen)
{
this.screen = screen;
}
public Rect WorkingArea
{
get { return this.GetRect(this.screen.WorkingArea); }
}
private Rect GetRect(Rectangle value)
{
return new Rect
{
X = value.X,
Y = value.Y,
Width = value.Width,
Height = value.Height
};
}
}
}
Basically the code is needed to set the max-Values for Height/Width of an Excel-Addin to the available working area of the display. The above application is just a very simple example to illustrate the problem.
For me it would be ok to just know that the 16 pixels are universally valid and independent from hard-/software. Nevertheless it would be great to get an Explanation whats the reason for this behaviour.
Greetings and THX in advance,
Sven
Why not use
WPF WindowState="Maximized"
see: How can I make a WPF window maximized on the screen with the mouse cursor?
I have an image that is inside of a tab item:
<TabItem x:Name="tabThreeTb" Header="Photos" HorizontalAlignment="Left" Height="22" VerticalAlignment="Top" Width="55" Margin="1,0,-1,0">
<Grid x:Name="tabThreeBdy" Background="#FFE5E5E5">
<Rectangle Fill="#FFE5E5E5" HorizontalAlignment="Left" Height="369" Margin="12,13,0,0" Stroke="Black" VerticalAlignment="Top" Width="467">
<Rectangle.Effect>
<DropShadowEffect/>
</Rectangle.Effect>
</Rectangle>
<TextBox x:Name="picNotesTextBox" HorizontalAlignment="Left" Height="415" Margin="498,10,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="299"/>
<Button x:Name="nxtPhotoBtn" Content="Next" HorizontalAlignment="Left" Margin="404,403,0,0" VerticalAlignment="Top" Width="75"/>
<Button x:Name="prevPhotoBtn" Content="Prev" HorizontalAlignment="Left" Margin="10,403,0,0" VerticalAlignment="Top" Width="75"/>
<Label x:Name="photoNumLbl" Content="1 of 4" HorizontalAlignment="Left" Margin="226,401,0,0" VerticalAlignment="Top" Width="42"/>
<Image x:Name="photoTabImage" HorizontalAlignment="Left" Height="369" Margin="12,13,0,0" VerticalAlignment="Top" Width="467" AllowDrop="True" DragEnter="photoTabImage_DragEnter"/>
</Grid>
</TabItem>
I am trying to use drag and drop to allow for the addition of photos to to the list that contains paths for the image source, though I can't seem to be able to fire the DragEnter routine...
I would like the drag and drop functionality to only be alive when the content is being dragged over the Image bounds.
Is there something I need to do for an Item that is nested in a tab control to allow this?
The issue is in that your app for some reason can't proceed standard events set. To fix that switch it to the tunneling model, by simply replacing your events on Preview versions (for instance replace DragEnter="photoTabImage_DragEnter" on to the PreviewDragEnter="photoTabImage_DragEnter")
Best regards,
Maks!
try add
<Label HorizontalAlignment="{Binding ElementName=photoTabImage, Path=HorizontalAlignment}"
Height="{Binding ElementName=photoTabImage, Path=Height}"
Width="{Binding ElementName=photoTabImage, Path=Width}"
Margin="{Binding ElementName=photoTabImage, Path=Margin}"
VerticalAlignment="{Binding ElementName=photoTabImage, Path=VerticalAlignment}"
AllowDrop="True" Drop="ContainerDrop" DragOver="ContainerDragOver"/>
after Image, and use event DragOver
if you need analyze drop object then add next code inside you class
private void ContainerDrop(object sender, DragEventArgs e)
{
StringBuilder sb = new StringBuilder();
foreach (string format in e.Data.GetFormats())
{
sb.AppendLine("Format:" + format);
try
{
object data = e.Data.GetData(format);
sb.AppendLine("Type:" + (data == null ? "[null]" : data.GetType().ToString()));
sb.AppendLine("Data:" + data.ToString());
}
catch (Exception ex)
{
sb.AppendLine("!!CRASH!! " + ex.Message);
}
sb.AppendLine("=====================================================");
}
Console.WriteLine(sb.ToString());
}
private void ContainerDragOver(object sender, DragEventArgs e)
{
e.Effects = DragDropEffects.Copy;
e.Handled = true;
}
I am showing a window. The instance is created and shown within the ViewModel (bad practice I know...)
NewWindow form = new NewWindow();
form.ShowDialog();
Within that form I have an OK_button which is doing stuff when it is pressed. There exist a ViewModel to this form which has the OK Command from the OK_Button.
After that button is pressed doing stuff I want to close that form programatically from within the viewmodel. How can I do that?
I use WPF
UPDATE
now lets see what I do wrong: Here the DataContext event is not fired although my Window with the ViewModel is shown!?
The window that is shown and must be closed from the ViewModel:
public partial class NewSchoolYearWindow : Window
{
public NewSchoolYearWindow()
{
InitializeComponent();
}
private void Window_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
NewSchoolYearViewModel vm = (NewSchoolYearViewModel)e.NewValue;
vm.CloseNewSchoolYearDialog += () => this.Close();
}
}
Why is the DataContextChanged even not fired?
I use this XAML in my Window:
<Window x:Class="TBM.View.NewSchoolYearWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ViewModel="clr-namespace:TBM.ViewModel"
Title="Start a new school year"
Height="412" Width="505"
WindowStartupLocation="CenterScreen"
WindowStyle="ThreeDBorderWindow"
ResizeMode="CanResize" DataContextChanged="Window_DataContextChanged">
<Window.Resources>
<ViewModel:NewSchoolYearViewModel x:Key="NewSchoolYearViewModelID" />
</Window.Resources>
<Grid DataContext="{Binding ., Source={StaticResource NewSchoolYearViewModelID}}" Name="MainGrid">
<TextBlock Height="27" HorizontalAlignment="Left" Margin="68,46,0,0" Name="textBlock1" Text="School year start" VerticalAlignment="Top" Width="98" />
<TextBlock Height="27" HorizontalAlignment="Left" Margin="68,93,0,0" Name="textBlock2" Text="School year end" VerticalAlignment="Top" Width="98" />
<TextBlock Height="27" HorizontalAlignment="Left" Margin="68,169,0,0" Name="textBlock4" Text="Database name:" VerticalAlignment="Top" Width="150" TextAlignment="Left" TextTrimming="CharacterEllipsis" />
<TextBlock Height="27" HorizontalAlignment="Left" Margin="68,215,0,0" Name="textBlock3" Text="Directory:" VerticalAlignment="Top" Width="63" TextAlignment="Left" TextTrimming="CharacterEllipsis" />
<TextBox IsReadOnly="True" Text="{Binding CurrentSchoolYear.Directory}" Height="23" HorizontalAlignment="Left" Margin="172,212,0,0" Name="textBox3" VerticalAlignment="Top" Width="224" />
<Button Command="{Binding OpenNewSchoolYearDialogCommand}" Content="DIR" Height="23" HorizontalAlignment="Right" Margin="0,211,27,0" Name="button1" VerticalAlignment="Top" Width="54" />
<Button Command="{Binding CreateNewSchoolYearCommand}" Content="OK" Height="23" HorizontalAlignment="Left" Margin="381,299,0,0" Name="button2" VerticalAlignment="Top" Width="75" />
<Button Content="Cancel" Height="23" HorizontalAlignment="Left" Margin="300,299,0,0" Name="button3" VerticalAlignment="Top" Width="75" />
<DatePicker Height="25" HorizontalAlignment="Left" Margin="172,42,0,0" SelectedDate="{Binding CurrentSchoolYear.Start}" SelectedDateFormat="Long" VerticalAlignment="Top" Width="175" />
<DatePicker Height="25" HorizontalAlignment="Left" Margin="172,89,0,0" SelectedDate="{Binding CurrentSchoolYear.End}" SelectedDateFormat="Long" VerticalAlignment="Top" Width="175" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="172,166,0,0" Name="textBox1" Text="{Binding CurrentSchoolYear.Name}" VerticalAlignment="Top" Width="175" />
</Grid>
</Window>
Declare an event in the ViewModel:
public event EventHandler<CloseRequestedEventArgs> CloseRequested;
protected virtual void OnCloseRequested(bool? dialogResult)
{
var handler = CloseRequested;
if (handler != null)
handler(this, new CloseRequestedEventArgs(dialogResult));
}
...
public class CloseRequestedEventargs : EventArgs
{
private readonly bool? _dialogResult;
public CloseRequestedEventargs(bool? dialogResult)
{
_dialogResult = dialogResult;
}
public bool DialogResult { get { return _dialogResult; } }
}
And handle it in the code-behind:
var vm = (MyViewModel)DataContext;
vm.CloseRequested += vm_CloseRequested;
...
private void vm_CloseRequested(object sender, CloseRequestedEventArgs e)
{
if (e.DialogResult.HasValue)
this.DialogResult = e.DialogResult; // sets the dialog result AND closes the window
else
this.Close();
}