I got a task that need to share camera view from a webcam into 2 Window. I've tried using singleton for create camera view only one time. The problem is that created instance can not share between 2 class. I'm now really confused. What am I doing wrong here?
MainWindow class
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
ReceptionMainWindow receptionMainWindow = new ReceptionMainWindow();
CustomerMainWindow customerMainWindow = new CustomerMainWindow();
receptionMainWindow.Show();
customerMainWindow.Show();
this.Hide();
}
}
Receptionist class
public partial class ReceptionMainWindow : Window
{
public ReceptionMainWindow()
{
InitializeComponent();
ReceptionWindowHoler.Content = CameraPage.getInstance();
}
}
Customer Class
public partial class CustomerMainWindow : Window
{
public CustomerMainWindow()
{
InitializeComponent();
CustomerWindowHoler.Content = CameraPage.getInstance();
}
}
private static CameraPage instance;
Camera class
public CameraPage()
{
InitializeComponent();
//DataContext = CameraViewModel.getInstance();
this.DataContext = this;
GetVideoDevices();
}
public static CameraPage getInstance()
{
if (instance == null)
instance = new CameraPage();
return instance;
}
You could create a Bitmap from the camera view and share it via events to the two other windows.
Take this answer as a workaround. There must be a better way.
Hi i need to be able to use a list from my Main Window in a Usercontrol i need to be able to edit and read from it in various Usercontrols.
MainWindow:
public partial class MainWindow : Window
{
public List<Termin> termine = new List<Termin>();
public MainWindow()
{
InitializeComponent();
}
}
Usercontrol:
public partial class KalenderAnsicht : UserControl
{
public KalenderAnsicht()
{
InitializeComponent();
}
private void SomeMethod()
{
//i need to be able to use the list here
}
}
You need to get a reference to the MainWindow one way or another. The easiest way to do this is probably to use the Application.Current.Windows property:
private void SomeMethod()
{
var mw = Application.Current.Windows.OfType<MainWindow>().FirstOrDefault();
List<Termin> termine = mw.termine;
//...
}
You could also consider making termine static:
public partial class MainWindow : Window
{
public static List<Termin> termine = new List<Termin>();
public MainWindow()
{
InitializeComponent();
}
}
...and access it directly without a reference to an instance of MainWindow:
private void SomeMethod()
{
List<Termin> termine = MainWindow.termine;
//...
}
I have a MainWindow class, and that is the main window of the app. I've created another class just below the MainWindow class, and I need to add an event to a Canvas that was created in MainWindow. The method I want to add as event is also in MainWindow.
public partial class MainWindow : Window
{
public void Moving(object sender, MouseEventArgs e)
{
bla bla;
}
public Canvas Getcanvas
{
get
{
return canvas;
}
}
}
public class Ka
{
public Ka()
{
MainWindow.Getcanvas.MouseMove += new MouseEventHandler(//HERE!!! I DONT KNOW WHAT GOES HERE, here should probably be MainWindow.Moving but I get error "An object reference.."
}
}
Please help me !
var mainWindowInstant = (MainWindow)App.Current.MainWindow;
mainWindowInstant.Getcanvas.MouseMove += new MouseEventHandler(...);
So my first attempt did everything out of the code behind, and now I'm trying to refactor my code to use the MVVM pattern, following the guidance of the MVVM in the box information.
I've created a viewmodel class to match my view class, and I'm moving the code out of the code behind into the viewmodel starting with the commands.
My first snag is trying to implement a 'Close' button that closes the window if the data has not been modified. I've rigged up a CloseCommand to replace the 'onClick' method and all is good except for where the code tries to run this.Close(). Obviously, since the code has been moved from a window to a normal class, 'this' isn't a window and therefore isn't closeable. However, according to MVVM, the viewmodel doesn't know about the view, so i can't call view.Close().
Can someone suggest how I can close the window from the viewmodel command?
I personally use a very simple approach: for every ViewModel that is related to a closeable View, I created a base ViewModel like this following example:
public abstract class CloseableViewModel
{
public event EventHandler ClosingRequest;
protected void OnClosingRequest()
{
if (this.ClosingRequest != null)
{
this.ClosingRequest(this, EventArgs.Empty);
}
}
}
Then in your ViewModel that inherits from CloseableViewModel, simply call this.OnClosingRequest(); for the Close command.
In the view:
public class YourView
{
...
var vm = new ClosableViewModel();
this.Datacontext = vm;
vm.ClosingRequest += (sender, e) => this.Close();
}
You don't need to pass the View instance to your ViewModel layer. You can access the main window like this -
Application.Current.MainWindow.Close()
I see no issue in accessing your main window in ViewModel class as stated above. As per MVVM principle there should not be tight coupling between your View and ViewModel i.e. they should work be oblivious of others operation. Here, we are not passing anything to ViewModel from View. If you want to look for other options this might help you - Close window using MVVM
My solution to close a window from view model while clicking a button is as follows:
In view model
public RelayCommand CloseWindow;
Constructor()
{
CloseWindow = new RelayCommand(CloseWin);
}
public void CloseWin(object obj)
{
Window win = obj as Window;
win.Close();
}
In View, set as follows
<Button Command="{Binding CloseWindowCommand}" CommandParameter="{Binding ElementName=WindowNameTobeClose}" Content="Cancel" />
I do it by creating a attached property called DialogResult:
public static class DialogCloser
{
public static readonly DependencyProperty DialogResultProperty =
DependencyProperty.RegisterAttached(
"DialogResult",
typeof(bool?),
typeof(DialogCloser),
new PropertyMetadata(DialogResultChanged));
private static void DialogResultChanged(
DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
var window = d as Window;
if (window != null && (bool?)e.NewValue == true)
window.Close();
}
public static void SetDialogResult(Window target, bool? value)
{
target.SetValue(DialogResultProperty, value);
}
}
then write this to you XAML, in the window tag
WindowActions:DialogCloser.DialogResult="{Binding Close}"
finally in the ViewModel
private bool _close;
public bool Close
{
get { return _close; }
set
{
if (_close == value)
return;
_close = value;
NotifyPropertyChanged("Close");
}
}
if you change the Close to true, the window will be closed
Close = True;
Here is the simplest and pure MVVM solution
ViewModel Code
public class ViewModel
{
public Action CloseAction { get; set; }
private void CloseCommandFunction()
{
CloseAction();
}
}
Here is XAML View Code
public partial class DialogWindow : Window
{
public DialogWindow()
{
ViewModel vm = new ViewModel();
this.DataContext = vm;
vm.CloseAction = Close;
}
}
This solution is quick and easy. Downside is that there is some coupling between the layers.
In your viewmodel:
public class MyWindowViewModel: ViewModelBase
{
public Command.StandardCommand CloseCommand
{
get
{
return new Command.StandardCommand(Close);
}
}
public void Close()
{
foreach (System.Windows.Window window in System.Windows.Application.Current.Windows)
{
if (window.DataContext == this)
{
window.Close();
}
}
}
}
MVVM-light with a custom message notification to avoid the window to process every notificationmessage
In the viewmodel:
public class CloseDialogMessage : NotificationMessage
{
public CloseDialogMessage(object sender) : base(sender, "") { }
}
private void OnClose()
{
Messenger.Default.Send(new CloseDialogMessage(this));
}
Register the message in the window constructor:
Messenger.Default.Register<CloseDialogMessage>(this, nm =>
{
Close();
});
This is very similar to eoldre's answer. It's functionally the same in that it looks through the same Windows collection for a window that has the view model as its datacontext; but I've used a RelayCommand and some LINQ to achieve the same result.
public RelayCommand CloseCommand
{
get
{
return new RelayCommand(() => Application.Current.Windows
.Cast<Window>()
.Single(w => w.DataContext == this)
.Close());
}
}
using MVVM-light toolkit:
In the ViewModel:
public void notifyWindowToClose()
{
Messenger.Default.Send<NotificationMessage>(
new NotificationMessage(this, "CloseWindowsBoundToMe")
);
}
And in the View:
Messenger.Default.Register<NotificationMessage>(this, (nm) =>
{
if (nm.Notification == "CloseWindowsBoundToMe")
{
if (nm.Sender == this.DataContext)
this.Close();
}
});
This is taken from ken2k answer (thanks!), just adding the CloseCommand also to the base CloseableViewModel.
public class CloseableViewModel
{
public CloseableViewModel()
{
CloseCommand = new RelayCommand(this.OnClosingRequest);
}
public event EventHandler ClosingRequest;
protected void OnClosingRequest()
{
if (this.ClosingRequest != null)
{
this.ClosingRequest(this, EventArgs.Empty);
}
}
public RelayCommand CloseCommand
{
get;
private set;
}
}
Your view model, inherits it
public class MyViewModel : CloseableViewModel
Then on you view
public MyView()
{
var viewModel = new StudyDataStructureViewModel(studyId);
this.DataContext = viewModel;
//InitializeComponent(); ...
viewModel.ClosingRequest += (sender, e) => this.Close();
}
Given a way, Please check
https://stackoverflow.com/a/30546407/3659387
Short Description
Derive your ViewModel from INotifyPropertyChanged
Create a observable property CloseDialog in ViewModel, Change CloseDialog property whenever you want to close the dialog.
Attach a Handler in View for this property change
Now you are almost done. In the event handler make DialogResult = true
first of all give your window a name like
x:Name="AboutViewWindow"
on my close button I've defined Command and Command Parameter like
CommandParameter="{Binding ElementName=AboutViewWindow}"
Command="{Binding CancelCommand}"
then in my view model
private ICommand _cancelCommand;
public ICommand CancelCommand
{
get
{
if (_cancelCommand == null)
{
_cancelCommand = new DelegateCommand<Window>(
x =>
{
x?.Close();
});
}
return _cancelCommand;
}
}
Most MVVM-compliant solution using HanumanInstitute.MvvmDialogs
Implement ICloseable interface in your ViewModel and that's it!
No code in your view whatsoever.
I've been using WPF for a while but I'm new to Commands, but would like to start using them properly for once. Following a code example, I've established a separate static Commands class to hold all of my commands, and it looks like this.
public static class Commands
{
public static RoutedUICommand OpenDocument { get; set; }
static Commands()
{
OpenDocument = new RoutedUICommand("Open Document", "OpenDocument", typeof(Commands));
}
public static void BindCommands(Window window)
{
window.CommandBindings.Add(new CommandBinding(OpenDocument, OpenDocument_Executed, OpenDocument_CanExecute));
}
private static void OpenDocument_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
// Should be set to true if an item is selected in the datagrid.
}
private static void OpenDocument_Executed(object sender, ExecutedRoutedEventArgs e)
{
}
}
My problem is that although the command is going to be bound to a Button control in MainWindow.xaml, the OpenDocument_CanExecute method needs to look at a DataGrid in MainWindow.xaml to see if an item is selected.
How can I wire things up such that the method can see the DataGrid?
SOLUTION
Inspired by Ken's reply (thanks again!), I put the following in place, which works perfectly.
MainWindow.xaml.cs
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
Loaded += delegate
{
DataContext = ViewModel.Current;
Commands.BindCommands(this);
};
}
}
ViewModel.cs
public class ViewModel
{
private static ViewModel _current;
public static ViewModel Current
{
get { return _current ?? (_current = new ViewModel()); }
set { _current = value; }
}
public object SelectedItem { get; set; }
}
Commands.cs
public static class Commands
{
public static RoutedUICommand OpenDocument { get; set; }
static Commands()
{
OpenDocument = new RoutedUICommand("Open Document", "OpenDocument", typeof(Commands));
}
public static void BindCommands(Window window)
{
window.CommandBindings.Add(new CommandBinding(OpenDocument, OpenDocument_Executed, OpenDocument_CanExecute));
}
private static void OpenDocument_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = ViewModel.Current.SelectedItem != null;
}
private static void OpenDocument_Executed(object sender, ExecutedRoutedEventArgs e)
{
}
}
ICommand implementations work best in the MVVM pattern:
class ViewModel : INotifyPropertyChanged {
class OpenDocumentCommand : ICommand {
public bool CanExecute(object parameter) {
return ViewModel.ItemIsSelected;
}
public OpenDocumentCommand(ViewModel viewModel) {
viewModel.PropertyChanged += (s, e) => {
if ("ItemIsSelected" == e.PropertyName) {
RaiseCanExecuteChanged();
}
};
}
}
private bool _ItemIsSelected;
public bool ItemIsSelected {
get { return _ItemIsSelected; }
set {
if (value == _ItemIsSelected) return;
_ItemIsSelected = value;
RaisePropertyChanged("ItemIsSelected");
}
}
public ICommand OpenDocument {
get { return new OpenDocumentCommand(this); }
}
}
Obviously, I left out a whole bunch of stuff. But this pattern has worked well for me in the past.
why even implement a command if you are tightly coupling it to UI implementation? Just respond to datagrid.SelectionChanged and code in what supposed to happen.
Otherwise, put it in the ViewModel. Have the ViewModel monitor it's state and evaluate when CanExe is true.
Edit
On the other hand, you can pass a parameter to your command, as well as Exe() & CanExe() methods
//where T is the type you want to operate on
public static RoutedUICommand<T> OpenDocument { get; set; }
If you are doing an MVVM solution, this would be the perfect time to implement a publish / subscribe aggregator that allows controls to "talk" to each other. The gist behind it is that the datagrid would publish an event, 'Open Document'. Subsequent controls could subscribe to the event and react to the call to 'Open Document'. The publish / subscribe pattern prevents tightly coupling the datagrid and the control. Do some searches for event aggregators and I think you'll be on your way.