[Problem] Why can not Pass Image between 2 Views by using the same ViewModel (MVVM)
-
The purpose of this code is open image file in a page and display it in another page. I had tried set ViewModel by using Singleton Pattern, but it didn't work.... If I integrate to one View, it can display the image correctly. But I need to separate the views. I have no idea what's wrong in this MVVM code....and how to fix it? Please point me how can I do or let me know what keyword I can search the toturial/sample. Thank you all. -- The OpenFile button is on DisplayControlView and display on DisplayView. The View Schema is as below: MainWindow.xaml (window) | |__ReviewView.xaml (page) | |__DisplayControlView.xaml (page) | |__DisplayPanelView.xaml (page) | |__DisplayView.xaml (page) -- DisplayControlView.xaml
...
...-- DisplayView.xaml
...
...
-- DisplayViewModel.cs
class DisplayViewModel : ViewModelBase
{
private DisplayImageModel image { get; set; }private ObservableCollection imagelist = new ObservableCollection(); public ObservableCollection ImageList { get { return imagelist; } set { imagelist = value; OnPropertyChanged(); } } public string ImagePath { get { return image.Path; } set { if (image.Path != value) { image.Path = value; OnPropertyChanged(); } } } public DisplayViewModel() { image = new DisplayImageModel(); ImagePath = @"C:\\Users\\oscartsai\\Desktop\\lenna.png"; } public bool CanExecute() { return true; } public RelayCommand OpenFile { get { return new RelayCommand(openFile, CanExecute); } } private void openFile() { string\[\] picExtName = new string\[\] { ".PNG", ".JPG", "JEPG", "BMP" }; OpenFileDialog dlgOpenFile = new OpenFileDialog() { Filter = "Picture|\*.jpg;\*.jpeg;\*.bmp;\*.png|All File|\*.\*" }; if (dlgOpenFile.ShowDialog() != true) { return; } if (picExtName.Any(System.IO.Path.GetExtension(dlgO
-
The purpose of this code is open image file in a page and display it in another page. I had tried set ViewModel by using Singleton Pattern, but it didn't work.... If I integrate to one View, it can display the image correctly. But I need to separate the views. I have no idea what's wrong in this MVVM code....and how to fix it? Please point me how can I do or let me know what keyword I can search the toturial/sample. Thank you all. -- The OpenFile button is on DisplayControlView and display on DisplayView. The View Schema is as below: MainWindow.xaml (window) | |__ReviewView.xaml (page) | |__DisplayControlView.xaml (page) | |__DisplayPanelView.xaml (page) | |__DisplayView.xaml (page) -- DisplayControlView.xaml
...
...-- DisplayView.xaml
...
...
-- DisplayViewModel.cs
class DisplayViewModel : ViewModelBase
{
private DisplayImageModel image { get; set; }private ObservableCollection imagelist = new ObservableCollection(); public ObservableCollection ImageList { get { return imagelist; } set { imagelist = value; OnPropertyChanged(); } } public string ImagePath { get { return image.Path; } set { if (image.Path != value) { image.Path = value; OnPropertyChanged(); } } } public DisplayViewModel() { image = new DisplayImageModel(); ImagePath = @"C:\\Users\\oscartsai\\Desktop\\lenna.png"; } public bool CanExecute() { return true; } public RelayCommand OpenFile { get { return new RelayCommand(openFile, CanExecute); } } private void openFile() { string\[\] picExtName = new string\[\] { ".PNG", ".JPG", "JEPG", "BMP" }; OpenFileDialog dlgOpenFile = new OpenFileDialog() { Filter = "Picture|\*.jpg;\*.jpeg;\*.bmp;\*.png|All File|\*.\*" }; if (dlgOpenFile.ShowDialog() != true) { return; } if (picExtName.Any(System.IO.Path.GetExtension(dlgO
You've got a .Contains function with no parameter.
if (picExtName.Any(System.IO.Path.GetExtension(dlgOpenFile.FileName).ToUpper().Contains))
It was only in wine that he laid down no limit for himself, but he did not allow himself to be confused by it. ― Confucian Analects: Rules of Confucius about his food
-
You've got a .Contains function with no parameter.
if (picExtName.Any(System.IO.Path.GetExtension(dlgOpenFile.FileName).ToUpper().Contains))
It was only in wine that he laid down no limit for himself, but he did not allow himself to be confused by it. ― Confucian Analects: Rules of Confucius about his food
It uses String[].Any() to indicate the parameter. The problem is it can't display selected image file on DisplayView (page).... As my original post mention, all the same code can work well in one ViewModel and one View. When I separate the code to one ViewModel and 3 Views, it can not work as my expected. It just can show open dialog for selecting file, but display nothing after selection. I think the problem will be the operation on one View(DisplayControlView) can not effect another View(DisplayView)
-
It uses String[].Any() to indicate the parameter. The problem is it can't display selected image file on DisplayView (page).... As my original post mention, all the same code can work well in one ViewModel and one View. When I separate the code to one ViewModel and 3 Views, it can not work as my expected. It just can show open dialog for selecting file, but display nothing after selection. I think the problem will be the operation on one View(DisplayControlView) can not effect another View(DisplayView)
I use code-behind to load images; that works. I also hook up the "ImageFailed" event; then you know why it's not working (somewhat). (MVVM has too much "indirection" for my brain).
It was only in wine that he laid down no limit for himself, but he did not allow himself to be confused by it. ― Confucian Analects: Rules of Confucius about his food
-
The purpose of this code is open image file in a page and display it in another page. I had tried set ViewModel by using Singleton Pattern, but it didn't work.... If I integrate to one View, it can display the image correctly. But I need to separate the views. I have no idea what's wrong in this MVVM code....and how to fix it? Please point me how can I do or let me know what keyword I can search the toturial/sample. Thank you all. -- The OpenFile button is on DisplayControlView and display on DisplayView. The View Schema is as below: MainWindow.xaml (window) | |__ReviewView.xaml (page) | |__DisplayControlView.xaml (page) | |__DisplayPanelView.xaml (page) | |__DisplayView.xaml (page) -- DisplayControlView.xaml
...
...-- DisplayView.xaml
...
...
-- DisplayViewModel.cs
class DisplayViewModel : ViewModelBase
{
private DisplayImageModel image { get; set; }private ObservableCollection imagelist = new ObservableCollection(); public ObservableCollection ImageList { get { return imagelist; } set { imagelist = value; OnPropertyChanged(); } } public string ImagePath { get { return image.Path; } set { if (image.Path != value) { image.Path = value; OnPropertyChanged(); } } } public DisplayViewModel() { image = new DisplayImageModel(); ImagePath = @"C:\\Users\\oscartsai\\Desktop\\lenna.png"; } public bool CanExecute() { return true; } public RelayCommand OpenFile { get { return new RelayCommand(openFile, CanExecute); } } private void openFile() { string\[\] picExtName = new string\[\] { ".PNG", ".JPG", "JEPG", "BMP" }; OpenFileDialog dlgOpenFile = new OpenFileDialog() { Filter = "Picture|\*.jpg;\*.jpeg;\*.bmp;\*.png|All File|\*.\*" }; if (dlgOpenFile.ShowDialog() != true) { return; } if (picExtName.Any(System.IO.Path.GetExtension(dlgO
Quote:
DisplayView.xaml
<Page.DataContext>
vm:DisplayViewModel/
</Page.DataContext>
...
<Image x:Name="imgDisplayView" Source="{Binding ImagePath}">
<Image.RenderTransform>
<TransformGroup>
<TranslateTransform/>
<RotateTransform/>
<ScaleTransform/>
</TransformGroup>
</Image.RenderTransform>
</Image>
...The problem is that your
DisplayPanelView
is setting itsDataContext
to a new instance of your viewmodel. The image path you set on theDataContext
of theDisplayControlView
will have no effect on the property of the separate viewmodel instance used as theDataContext
forDisplayPanelView
. You need both controls to use the same viewmodel instance for theirDataContext
. Depending on how yourReviewView
viewmodel is set up, you probably want to expose a singleDisplayViewModel
instance as a property on that viewmodel, and have bothDisplay...
views bound to that. For example:public class ReviewViewModel : ViewModelBase
{
private DisplayViewModel _display = new DisplayViewModel();public DisplayViewModel { get { return \_display; } set { SetValue(ref \_display, value); } }
}
ReviewView.xaml:
<views:DisplayControlView DataContext="{Binding Path=DisplayViewModel}" />
<views:DisplayPanelView DataContext="{Binding Path=DisplayPanelView}" />Remove the
<Page.DataContext>
from bothDisplayControlView
andDisplayPanelView
pages.
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer
-
Quote:
DisplayView.xaml
<Page.DataContext>
vm:DisplayViewModel/
</Page.DataContext>
...
<Image x:Name="imgDisplayView" Source="{Binding ImagePath}">
<Image.RenderTransform>
<TransformGroup>
<TranslateTransform/>
<RotateTransform/>
<ScaleTransform/>
</TransformGroup>
</Image.RenderTransform>
</Image>
...The problem is that your
DisplayPanelView
is setting itsDataContext
to a new instance of your viewmodel. The image path you set on theDataContext
of theDisplayControlView
will have no effect on the property of the separate viewmodel instance used as theDataContext
forDisplayPanelView
. You need both controls to use the same viewmodel instance for theirDataContext
. Depending on how yourReviewView
viewmodel is set up, you probably want to expose a singleDisplayViewModel
instance as a property on that viewmodel, and have bothDisplay...
views bound to that. For example:public class ReviewViewModel : ViewModelBase
{
private DisplayViewModel _display = new DisplayViewModel();public DisplayViewModel { get { return \_display; } set { SetValue(ref \_display, value); } }
}
ReviewView.xaml:
<views:DisplayControlView DataContext="{Binding Path=DisplayViewModel}" />
<views:DisplayPanelView DataContext="{Binding Path=DisplayPanelView}" />Remove the
<Page.DataContext>
from bothDisplayControlView
andDisplayPanelView
pages.
"These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer
Here is something can't run properly. Is below code is written in NEW class called ReviewViewModel?
public class ReviewViewModel : ViewModelBase
{
private DisplayViewModel _display = new DisplayViewModel();public DisplayViewModel { get { return \_display; } set { SetValue(ref \_display, value); } }
}
But the Intellisense will show warning about the declaration of DisplayViewModel and the function of SetValue is invalid.... What prerequisites are needed for this code? Sincere thank Richard Master to point me!! All Views need one ViewModel instance, and I had no idea about how to set one ViewModel instance until this post point me. And thank Gerry join this discussion.
-
Here is something can't run properly. Is below code is written in NEW class called ReviewViewModel?
public class ReviewViewModel : ViewModelBase
{
private DisplayViewModel _display = new DisplayViewModel();public DisplayViewModel { get { return \_display; } set { SetValue(ref \_display, value); } }
}
But the Intellisense will show warning about the declaration of DisplayViewModel and the function of SetValue is invalid.... What prerequisites are needed for this code? Sincere thank Richard Master to point me!! All Views need one ViewModel instance, and I had no idea about how to set one ViewModel instance until this post point me. And thank Gerry join this discussion.
In addition: ReviewView.xaml
-
The purpose of this code is open image file in a page and display it in another page. I had tried set ViewModel by using Singleton Pattern, but it didn't work.... If I integrate to one View, it can display the image correctly. But I need to separate the views. I have no idea what's wrong in this MVVM code....and how to fix it? Please point me how can I do or let me know what keyword I can search the toturial/sample. Thank you all. -- The OpenFile button is on DisplayControlView and display on DisplayView. The View Schema is as below: MainWindow.xaml (window) | |__ReviewView.xaml (page) | |__DisplayControlView.xaml (page) | |__DisplayPanelView.xaml (page) | |__DisplayView.xaml (page) -- DisplayControlView.xaml
...
...-- DisplayView.xaml
...
...
-- DisplayViewModel.cs
class DisplayViewModel : ViewModelBase
{
private DisplayImageModel image { get; set; }private ObservableCollection imagelist = new ObservableCollection(); public ObservableCollection ImageList { get { return imagelist; } set { imagelist = value; OnPropertyChanged(); } } public string ImagePath { get { return image.Path; } set { if (image.Path != value) { image.Path = value; OnPropertyChanged(); } } } public DisplayViewModel() { image = new DisplayImageModel(); ImagePath = @"C:\\Users\\oscartsai\\Desktop\\lenna.png"; } public bool CanExecute() { return true; } public RelayCommand OpenFile { get { return new RelayCommand(openFile, CanExecute); } } private void openFile() { string\[\] picExtName = new string\[\] { ".PNG", ".JPG", "JEPG", "BMP" }; OpenFileDialog dlgOpenFile = new OpenFileDialog() { Filter = "Picture|\*.jpg;\*.jpeg;\*.bmp;\*.png|All File|\*.\*" }; if (dlgOpenFile.ShowDialog() != true) { return; } if (picExtName.Any(System.IO.Path.GetExtension(dlgO
One thing I see right off the bat is that when you use DataContext you are instantiating DisplayViewModel.
You basically created two instances of DisplayViewModel. One fix would be to instantiate it somewhere else in C# :
DisplayViewModel displayViewModel = new DisplayViewModel();
Then add to each page then for each page in C# on initialization add:
this.DataContext = ????.displayViewModel
Now they will both point to the same instance.
So many years of programming I have forgotten more languages than I know.
-
One thing I see right off the bat is that when you use DataContext you are instantiating DisplayViewModel.
You basically created two instances of DisplayViewModel. One fix would be to instantiate it somewhere else in C# :
DisplayViewModel displayViewModel = new DisplayViewModel();
Then add to each page then for each page in C# on initialization add:
this.DataContext = ????.displayViewModel
Now they will both point to the same instance.
So many years of programming I have forgotten more languages than I know.
Thank for point me. Actually, I had solved this problem a few moment ago... XD Here is my solution: 1. Using singleton-pattern to fix one execution instance 2. At each View code-behind(???.xmal.cs) which needs to using the same ViewModel, I add below code
this.context = viewmodel.instance
BTW, I also ask in below Taiwan IT forum......and self-question at below to show my detail solution XD [問題] MVVM架構下,如何多個View共用同一個ViewModel變數 - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天[^] For you reference~~~ Thanks guys again :)
-
Thank for point me. Actually, I had solved this problem a few moment ago... XD Here is my solution: 1. Using singleton-pattern to fix one execution instance 2. At each View code-behind(???.xmal.cs) which needs to using the same ViewModel, I add below code
this.context = viewmodel.instance
BTW, I also ask in below Taiwan IT forum......and self-question at below to show my detail solution XD [問題] MVVM架構下,如何多個View共用同一個ViewModel變數 - iT 邦幫忙::一起幫忙解決難題,拯救 IT 人的一天[^] For you reference~~~ Thanks guys again :)
I have also seen static's used. Not a "static" fan but it works. Static's have there place. The reason Serilog is so easy to use and hence popular is because of static's.
So many years of programming I have forgotten more languages than I know.