public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
private void ToggleButton_Checked(object sender, RoutedEventArgs e)
{
switch ((sender as Button).Content.ToString())
{
case "UserControl 1":
AddItemToContainer(new UserControl1());
break;
case "UserControl 2":
AddItemToContainer(new UserControl2());
break;
case "UserControl 3":
AddItemToContainer(new UserControl3());
break;
default:
break;
}
}
void AddItemToContainer(UIElement _myElement)
{
Grid.SetColumn(_myElement, 1);
HostContainer.Children.Add(_myElement);
}
}
}
}
With this I can open a new userControl in myMainwindow
Let’s say something like adding child to myMainWinodw,Now I’m trying to click on a button from my userControl so I open another userControl that take the place of the first one
I explain:
I have the mainWindows it has 3 button first one to open the first UserControl the second one to open the second userControl and the third to open the last UserControl,imagine that I opened the first UserControl let’s call it UC1,
In the UC1 I have a button to open the second userControl (let’s call it UC2) I like that when I clik the button from the UC1 the UC2 is opened and take the place of the UC1 (of course the UC2 is still a child of myMainWinodw)
I have alredy try to call the AddItemToContainer methode from other methode but nothing is happened
Any suggestion please
This approach may help:
Call the container control and modify it's Children.This example assumes that the container control is a Grid.
C# Code for Window1
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
HostContainer.Children.Add(new UserControl1(HostContainer));
}
}
C# Code for UserControl1
public partial class UserControl1 : UserControl
{
Grid _hostContainer;
public UserControl1(Grid HostContainer)
{
InitializeComponent();
_hostContainer = HostContainer;
}
private void ToggleButton_Checked(object sender, RoutedEventArgs e)
{
UserControl2 UC2 = new UserControl2();
_hostContainer.Children.Add(UC2);
}
}
Yes that helps but it does not realy take the place of the UC1 It just puch it a litel bit and take a litelle space of the mainWindow here is some snaps with explanation if you like http://startou.com/file/630-9411954b18.html
Related
Sorry for the stupid question but I can't get it to work.
I got a MainWindow that opens another window.
public static Window2 LoadWindow = new Window2();
public MainWindow()
{
InitializeComponent();
LoadWindow.Show();
Later in the code, I Start a function that creates a Background worker in the new window
if (MainWindow.Start == true)
{
MainWindow.LoadWindow.LoadImage(null, null);
MainWindow.Start = false;
}
public void LoadImage(object sender, RoutedEventArgs e)
{
worker = new BackgroundWorker();
...
And then I tried this to Change the Visibility of the MainWindow.
private void worker_Completed(object sender, RunWorkerCompletedEventArgs e)
{
Application.Current.Dispatcher.Invoke(new Action(() => {
Application.Current.MainWindow.Visibility = Visibility.Visible;
}));
}
I thought Application.Current.MainWindow would point to my MainWindow but the debugger said that Window2 is the Current.MainWindow.
Actually, I am completely confused about the MainWindow.
Typically I initialize a class with a name and use it with that name. (e.g. Window2=class, LoadWindow=it's name)
But what is the name of the MainWindow or how can I interact with it from another window. It's so confusing when the MainWindow != the MainWindow >.<.
You could either inject LoadWindow with a reference to the MainWindow when you create it in the constructor, or you could get a reference to the MainWindow using the Application.Current.Windows collection:
var mainWindow = Application.Current.Windows.OfType<MainWindow>().FirstOrDefault();
if (mainWindow != null)
mainWindow.Visibility = Visibility.Visible;
i have two separate projects inside a solution, one is a wpf the other is windows form and i have referenced the winform to the wpf project.. Inside the wpf window is an image control, when clicked, a windows form with a button would appear.
How i can be able to change the image source of the image control inside the wpf form when the button inside the winform is clicked...
i have seen a similar question to this but i cant understand the answers...
You could pass a delegate/Action into the Winform to perform the action
Here is a very quick example
WPF
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
// pass in the method you want to call when the winform button is clicked
var winform = new Form1(() => ChangeImage()).ShowDialog();
}
private void ChangeImage()
{
// your change image logic
}
}
Winforms
public partial class Form1 : Form
{
private Action _action;
public Form1()
{
InitializeComponent();
}
public Form1(Action action)
{
_action = action;
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
if (_action != null)
{
// call the method in the WPF form
_action.Invoke();
}
}
}
I've just started a new project in which the presentation layer will be done by WPF and MVVM Light by GalaSoft.
I need a lot of views and it's not clear to me how to manage navigation through windows.
First of all, the templates offered in MVVM Light for creating a new "WPF MVVM View" create a new Window that is not possible to use for navigation by frame (I mean, by putting a frame in mainView and changing the source path to navigate).
Do I simply have to change Window to Page for all the views I create using templates?
Or is there a different way to perform navigation in WPF with the MVVM Light toolkit?
I usually use a ContentControl to display dynamic content. It's Content property is usually bound to a CurrentViewModel property in the parent ViewModel, and DataTemplates are used to tell WPF how to draw the child ViewModels.
To change views, simply change the CurrentViewModel property in the parent ViewModel
You can find an example at this article of mine
Eventually I did it this way.
Following the idea of o_q, I created NavigationWindow as MainWindow and changed all the the views to page.
Then, I created an inteface and a class which using Navigation:
public interface INavigationService
{
event NavigatingCancelEventHandler Navigating;
void NavigateTo(Uri pageUri);
void GoBack();
}
public class NavigationService : INavigationService
{
private NavigationWindow _mainFrame;
#region Implementation of INavigationService
public event NavigatingCancelEventHandler Navigating;
public void NavigateTo(Uri pageUri)
{
if (EnsureMainFrame())
{
_mainFrame.Navigate(pageUri);
}
}
public void GoBack()
{
if (EnsureMainFrame()
&& _mainFrame.CanGoBack)
{
_mainFrame.GoBack();
}
}
#endregion
private bool EnsureMainFrame()
{
if (_mainFrame != null)
{
return true;
}
_mainFrame = System.Windows.Application.Current.MainWindow as NavigationWindow;
if (_mainFrame != null)
{
// Could be null if the app runs inside a design tool
_mainFrame.Navigating += (s, e) =>
{
if (Navigating != null)
{
Navigating(s, e);
}
};
return true;
}
return false;
}
}
Then, in viewModelLocator I created all the const string nedded to store the paths to my views:
public class ViewModelLocator
{
#region Views Paths
public const string FrontendViewPath = "../Views/FrontendView.xaml";
public const string BackendViewPath = "../Views/BackendView.xaml";
public const string StartUpViewPath = "../Views/StartUpView.xaml";
public const string LoginViewPath = "../Views/LoginView.xaml";
public const string OutOfOrderViewPath = "../Views/OutOfOrderView.xaml";
public const string OperativeViewPath = "../Views/SubViews/OperativeView.xaml";
public const string ConfigurationViewPath = "../Views/SubViews/ConfigurationView.xaml";
#endregion
}
In App.cs, in the Application_Startup event handler, with the help of Unity IoC I registered a singleton of NavigationService:
public partial class App : System.Windows.Application
{
private static IUnityContainer _ambientContainer;
public static IServiceLocator AmbientLocator { get; private set; }
...
private void Application_Startup(object sender, System.Windows.StartupEventArgs e)
{
_ambientContainer =
new UnityContainer();
_ambientContainer.RegisterType<INavigationService, NavigationService>(new ContainerControlledLifetimeManager());
AmbientLocator = new UnityServiceLocator(_ambientContainer);
ServiceLocator.SetLocatorProvider(() => AmbientLocator);
Now, in my ViewModelLocator, I can register a "Galasoft" message to catch all the events and navigate to a page; in the constructor I have:
public ViewModelLocator()
{
CreateMain();
CreateFrontend();
CreateBackend();
CreateStartUp();
CreateOperative();
CreateLogin();
CreateConfiguration();
CreateOutOfOrder();
// Set Startup Page...
ServiceLocator.Current.GetInstance<INavigationService>().NavigateTo(new Uri(StartUpViewPath, UriKind.Relative));
Messenger.Default.Register<MoveToViewMessage>(this, message =>
{
switch (message.StateInfo.StateType)
{
case StateType.StartUpState:
ServiceLocator.Current.GetInstance<INavigationService>().NavigateTo(new Uri(StartUpViewPath,UriKind.Relative));
break;
case StateType.LoginState:
ServiceLocator.Current.GetInstance<INavigationService>().NavigateTo(new Uri(LoginViewPath, UriKind.Relative));
break;
case StateType.OperativeState:
ServiceLocator.Current.GetInstance<INavigationService>().NavigateTo(new Uri(OperativeViewPath, UriKind.Relative));
break;
case StateType.ConfigurationState:
ServiceLocator.Current.GetInstance<INavigationService>().NavigateTo(new Uri(ConfigurationViewPath, UriKind.Relative));
break;
case StateType.ClosedState:
case StateType.OutOfOrderState:
ServiceLocator.Current.GetInstance<INavigationService>().NavigateTo(new Uri(OutOfOrderViewPath, UriKind.Relative));
break;
default:
ServiceLocator.Current.GetInstance<INavigationService>().NavigateTo(new Uri(StartUpViewPath, UriKind.Relative));
break;
}
});
}
In this way I keep all the viewModels "ignorant"... they don't know anything about navigation, plus I don't have code behind.
If I need to navigate by using a button from a view I can resolve NavigationService from the connected viewModel and navigate to the Page I need.
And, most important thing, it works!
For a navigable application, you'll want your start up view to be a NavigationWindow instead of a Window
<NavigationWindow
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="MainWindow"
Title="My Application Title"
Height="300"
Width="400" />
Code behind:
using System.Windows.Navigation;
public partial class MainWindow : NavigationWindow
{
public MainWindow()
{
InitializeComponent();
}
}
The MVVM Light view templates use Window, but as you have guessed, you can just change it. If you want to be able to navigate to and from this view, make it a Page.
This is how you navigate:
<Page
x:Class="Page1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Page1">
<Grid>
<!-- this button will navigate to another page -->
<Button
Content="Go to Page 2"
Click="Button_Click" />
</Grid>
</Page>
Code Behind:
using System.Windows;
using System.Windows.Controls;
public partial class Page1 : Page
{
public Page1()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
// the Page class has a property "NavigationService" which allows you to navigate.
// you can supply the "Navigate" method with a Uri or an object instance of the page
base.NavigationService.Navigate(new Page2());
}
}
In my XAML I have a Button, with a button click event. I initialize the component in my MainWindow class : RibbonWindow. I have a the Button Click function in a separate class, but error window gives me "FooApplication.MainWindow" does not contain a definition for fooBtn_Click", below is my code
namespace FooApplication1 {
public partial class MainWindow : RibbonWindow
{
public MainWindow()
{
InitializeComponent();
}
}
/* in another .cs class file located in the same project */
namespace FooApplication1
{
public partial class Jenny : MainWindow
{
public void btnApplyL_Click(object sender, EventArgs e)
{
MessageBox.Show("Hello");
}
}
}
I tried to give Jenny a RibbonWindow partial, thinking it might be the issue, but gives error. What is wrong?
Your XAML file needs to point to the class responsible for the event handling via the class attribute.
x:Class="FooApplication1.Jenny"
Defining event handlers within the XAML forces the use of the class attribute as it will dictate where the handlers exist. You can still have the partial classes; it's just that the XAML needs to know which class is responsible for the event handling which modifying the class attribute will address.
In addition you will need to move the InitializeComponent(); call from the MainWindow class to the Jenny class.
public partial class Jenny : MainWindow
{
public Jenny()
{
InitializeComponent();
}
...
}
In my TabControl using WPF,C#.I entering Text to ListBox in one TabItem from the click event in TabControl. But the ListBox does not display the Text. When I debug, I can find that the ListBox has count:1. Here is the code:
namespace Tabcontrol
{
public partial class PresetTab : UserControl //3rd Tabitem ,preset.xaml.cs
{
public PresetTab()
{
InitializeComponent();
}
public void AddPresetmenu(string pMenu)
{
menubox.Items.Add(pMenu); //menubox is listbox
}
}
}
namespace Tabcontrol
{
public partial class ToolBar : UserControl
{
PresetTab tab = new PresetTab();
public ToolBar()
{
InitializeComponent();
}
public void Click(object sender, MouseButtonEventArgs e)
{
Add("TAB MENU");
}
public void Add(string menu)
{
tab.AddPresetmenu(menu); //Im calling from tabcontrol,toolbar.xaml.cs
}
}
}
It would be easier to say for sure if you would have added your XAML code as well, but it seems to me that your adding the strings directly to the Items property and aren't applying a DataTemplate specifying how to display the strings. So either apply a DataTemplate which turns the string into a UIElement, e.g. a TextBlock, or try to add the TextBlocks in your code instead of strings.
public void AddPresetmenu(string pMenu)
{
TextBlock tb= new TextBlock();
tb.Text = pMenu;
menubox.Items.Add(tb);
}
Hope this helps, if not please include your XAML, this will make it easier to spot the problem.