I have problem with base classes in WPF. I try to make a base class with some base elements, so that other windows can inherit these components. But all that i have, when I inherit base class is only empty window, without these elements. For better understanding i put my code here:
using XSoftArt.WPFengine;
namespace XSoftArt
{
public class WindowBase : Window
{
public WindowBase()
{
}
}
Code of the Windows, whitch inherits WindowBase:
namespace XSoftArt.WPFengine
{
public partial class NewAbility : WindowBase
{
public NewAbility()
{
base.ChildForm = this; InitializeComponent();
}
}
}
Or maybe someone can put an working example or link with implemented base classes in wpf?
Thanks
I don't think you really need to do what you are doing, but it is feasible. I think you are just forgetting to call the base class constructor.
using XSoftArt.WPFengine;
namespace XSoftArt
{
public class WindowBase : Window
{
//call base ctor
public WindowBase() : base()
{
}
}
}
You'll need to do this from your inherited classes as well:
namespace XSoftArt.WPFengine
{
public partial class NewAbility : WindowBase
{
public NewAbility() : base()
{
base.ChildForm = this; InitializeComponent();
}
}
}
And if you also have a XAML-defined view, you'll need to make sure your view is a WindowBase. To do this, change this:
<Window x:Class="MyApp.MyView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
...
>
<Grid>
</Grid>
</Window>
To this:
<local:WindowBase x:Class="MyApp.MyView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:XSoftArt;"
...
>
<Grid>
</Grid>
</local:WindowBase>
If you look at this class in Reflector you will see that the constructor calls the Window class's own "Initialize()" method, which sets a lot of things in motion. Specifically it appears to hook itself up to the Dispatcher, which is the work queue for all UI events.
In particular, you want to ensure that the InitializeComponent() method of the base class is called - this is the function that creates the controls that you defined in XAML.
Making a derived class is great if you want to inherit both controls and behaviour, but consider using Templates for a more flexible way of managing a common set of controls.
I don't think I'd ever use inheritance in WPF the way you're trying to use it.
I'll try and take a stab at answering your question. If I'm understanding you correctly, you're trying something like this:
You're creating a window that has both a XAML file and a code-behind.
You're adding "base elements" to the XAML for your window... I'm not sure what you mean by "base element", but I'm going to assume you mean you're adding UI elements to your window.
You're creating another window that "derives" from your first window in the code-behind, and the problem is that you're not seeing the UI elements on it from your "base" window.
If that is what you want to accomplish with WPF, I'd personally recommend against it, just because I'm personally not a fan of inheritance and have seen firsthand the dangers of letting inheritance get out of hand.
What you could try instead is organize your "base" UI elements into WPF UserControls. This tutorial might be able to guide you in the right direction. Good luck!
Related
I got a warning that this may be a subjective question and might be closed, but I'm going to ask anyway.
I'm basically trying to access a button on my MainWindow in a WPF application from a UserControl that gets loaded up from within the MainWindow.
I'm currently accessing it like this from the UserControl's code behind:
((MainWindow)Application.Current.MainWindow).btnNext
But it does look messy, and from what I've read is not considered a best practice. Anyone able to provide an answer that constitutes a best practice for Accessing controls / properties from the current instance of a MainWindow - or any other active windows / views for that matter?
You can get a reference to the parent window of the UserControl using the Window.GetWindow method. Call this once the UserControl has been loaded:
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
this.Loaded += (s, e) =>
{
MainWindow parentWindow = Window.GetWindow(this) as MainWindow;
if (parentWindow != null)
{
//...
}
};
}
}
You could also access all open windows using the Application.Current.Windows property:
MainWindow mainWindow = Application.Current.Windows.OfType<MainWindow>().FirstOrDefault();
Which one to use depends on your requirements. If you want a reference to the application's main window for some reason, you could stick with your current approach. If you want a reference to the parent window of the UserControl, using the Window.GetWindow method would be better.
The best practice is generally to use the MVVM design pattern and bind UI controls to source properties of a view model that may be shared by several views. But that's another story. You could refer to the following link for more information about the MVVM pattern: https://msdn.microsoft.com/en-us/library/hh848246.aspx
i'm using Prism-MEF-WPF and Sometimes i need view model gets constructed from the XAML
of the view, so the container is not involved and can’t do the dependency injection
automatically (as there is no Export attribute used with VM).so there should be some
class in Prism-WPF like CompositionInitializer to enable me to ask the container to
do the injection.In case there is equivalent class how to use it, and in case there is
no equivalent how to construct view model from xaml of the view knowing that i use MEF.
Thanks in advance.
The problem is that you can't create an object in XAML if it doesn't have a parameterless constructor.
Using the ServiceLocator, you can achieve this. It will work as an IoC (and is set up by Prism/MEF, you just have to drop the .dll):
The xaml:
<Window.DataContext>
<local:ViewModel/>
</Window.DataContext>
The code-behind:
class ViewModel : NotificationObject
{
public ViewModel()
{
var firstDependency = ServiceLocator.Current.GetInstance<FirstDependencyType>();
//... more dependencies here instead of as constructor parameters
}
//class code omitted for brievity
}
Here is the right answer which i got from Agustin Adami "http://blogs.southworks.net/aadami":
Based on my understanding the view model can be instantiated in XAML as the view’s DataContext only if a view model does not have any constructor arguments. And as far as I know creating objects defined in XAML by partnering with an Inverse of Control Container is currently not supported.
Regarding the CompositionInitializer class, as far as I know there is no equivalent class for WPF, on the other hand regarding this topic, I believe you could find the following blog post interesting:
•http://reedcopsey.com/2010/03/26/mef-compositioninitializer-for-wpf/
Also, I believe an alternative for this could be registering the CompositionContainer class like mentioned in this thread:
http://compositewpf.codeplex.com/discussions/311933
As this could let you retrieve this class for example in your view model's constructor, in order to call the SatisfyImportsOnce method to satisfy the Imports defined in the passed class:
this.compositionContainer =ServiceLocator.Current.GetInstance();
this.compositionContainer.SatisfyImportsOnce(this);
Bootstrapper class is what you are looking for. It uses UnityContainer for injecting dependencies. This link here might be of your interest too..
EDIT
If i am getting right, you want to create a ViewModel from your xaml which can be achieved like this(Here local is namespace of your ViewModel class) -
<Window.DataContext>
<local:ViewModel/>
</Window.DataContext>
In winform, we can inherit easily. But in WPF, we can't inherit class which contains XAML. So whenever I need to generalize some window's attribute, I create a base class without XAML. For example, I want to make all windows start up at center screen. I use code behind in the base class (this class doesn't contain XAML)
namespace VBDAdvertisement
{
public class BaseWindow:Window
{
public BaseWindow()
{
this.WindowStartupLocation = WindowStartupLocation.CenterScreen;
}
}
}
That is just for a simple task. In my opinion, for more complex task, using code behind line by line is not a good idea. So I wonder if there is a better way to inherit window in WPF (something closer to winform inheritance) ?
I am new in the Wpf & Mvvm world , but I have found a couple of examples and just found that there is some different way to instantiate the model. I would like to know the best/correct way to do it. both ways are using Unity
What I've foud:
var navigatorView = new MainView();
navigatorView.DataContext = m_Container.Resolve<INavigatorViewModel>();
m_RegionManager.Regions["NavigatorRegion"].Add(navigatorView);
What I did:
var navigatorView = m_Container.Resolve<MainView>;
m_RegionManager.Regions["NavigatorRegion"].Add(navigatorView);
and I changed the constructor to receive viewmodel so I can point the datacontext to it:
public MainView(NavigatorViewModel navigatorViewModel)
{
this.DataContext = navigatorViewModel;
}
Other examples I've found another way like:
...vm = new viewmodel
...m = new model
v.model = vm;
get/set DataContext
cheers
I like Igor's suggestion, but without the viewmodel having knowledge of the view. I prefer my dependencies to go one direction (View -> ViewModel -> Model).
What I do is ViewModel-First and just DataTemplate the viewmodel. So I do this:
MainViewModel mainViewModel = container.Resolve<MainViewModel>();
region.Add(mainViewModel, "MainView");
region.Activate(mainViewModel);
With the addition of the ViewModel -> View mapping done with a WPF datatemplate (I don't think this approach is possible with Silverlight, though)
App.xaml:
<Application.Resources>
<DataTemplate DataType="{x:Type viewModels:MainViewModel}">
<views:MainView />
</DataTemplate>
</Application.Resources>
That's it! I love this approach. I like the way it feels like magic. It also has the following advantages:
Don't have to modify constructors to suit the mapping
Don't have to register type for IMyViewModel in the container... you can work with concrete types. I like to keep my registrations to application services like IViewRegistry or ILogger... those kinds of things
You can change the mapping using resources scoped to a particular view that a region is in (this is nice if you want to reuse your ViewModels but want them to look different in different areas of the application
What you got there makes sense and in both cases is a View-first approach to creating a viewmodel. I.e. the view creates the ViewModel. In the original example the viewmodel is created outside of the view (and is sometimes referred to as marriage pattern), but as far as I am concerned that's the same thing - creation of the view creates the ViewModel.
If this suits your needs stick with it. Another approach you might look into is ViewModel first where the viewmodel takes a dependency on the view like so:
//In the bare-bones(i.e. no WPF dependencies) common interface assembly
interfac IView {
void ApplyViewModel(object viewmodel);
}
interface IMainView : IView {
//this interface can actually be empty.
//It's only used to map to implementation.
}
//In the ViewModel assembly
class MainViewModel {
public MainViewModel(IMainView view) {
view.ApplyViewModel(this);
}
}
public partial class MainView : UserControl, IMainView {
void ApplyViewModel(object viewmodel){
DataContext = viewmodel;
}
}
Then you can inject this view like so:
IRegion region = regionManager.Regions["MainRegion"];
//This might look strange as we are resolving the class to itself, not an interface to the class
//This is OK, we want to take advantage of the DI container
//to resolve the viewmodel's dependencies for us,
//not just to resolve an interface to the class.
MainViewModel mainViewModel = container.Resolve<MainViewModel>();
region.Add(mainViewModel.View, "MainView");
region.Activate(ordersView.View);
How do you pass "this" to the constructor for ObjectDataProvider in XAML.
Lets say my presenter class is:
public class ApplicationPresenter(IView view){}
and that my UserControl implements IView.
What do I pass to the ConstructorParameters in the code below so that the UserControl can create the ApplicationPresenter using the default constructor?
<ObjectDataProvider x:Key="ApplicationPresenterDS"
ObjectType="{x:Type Fenix_Presenters:ApplicationPresenter}"
ConstructorParameters="{ ?? what goes here ??}" d:IsDataSource="True" />
I only need to do this so that I can use Blend 2. I know that I can do this in the code behind, but if I do I can't instantiate the class from within Blend. I also know that I can create a parameterless constructor for ApplicationPresenter and pass it a dummy class that implements IView, but I would rather do this in markup if at all possible.
My code behind at the moment is:
public MyUserControl()
{
InitializeComponent();
DataContext = new ApplicationPresenter(this);
}
I'm just starting with Wpf and was under the misapprehension that I should be trying to do everything in XAML. I've just watched a few videos from WindowsClient.net which are starting to clear some things up. But boy is this a complex technology!!!
i don't know if it works, but you could give your user control a name , e.g.
x:Name="myUserCotrol"
and then use it in a binding:
... ConstructorParameters="{Binding ElementName=myUserControl}" ...
this could work
This will be directly supported (if memory serves well) in the next version of XAML as demonstrated by Rob Relyea at this year's PDC.