I have a task which has to implement the MVVM pattern.
I have a MainWindow with a button, successfully tied it up to a working and tested command.
My goal is to navigate to an existing Page on button click, but the problem is:
-NullReferenceException()
Corresponding MainWindow.xaml part
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Frame x:Name="MainFrame" NavigationUIVisibility="Hidden" Content="{Binding MainFrame}" ></Frame>
ETC
Corresponding ViewModels clickCommand:
private void ExecuteMethod(object parameter)
{
View.Home homePage = new View.Home();
mainFrame.Content = homePage;
MainFrame.Navigate(homePage);
}
Page to be loaded is an existing page with several controls in it, yet I fail to even navigate to there, since
mainFrame.Content = homePage;
throws a NullReferenceException(object reference not set to an instance of an object)
What am I missing?
Related
I have C# WPF application and window with ribbon control and text-box. The ribbon defines many keyboard-shortcuts for the window, e.g. F1, D etc. While the cursor is in the text-box, pressing key D causes calling function associated with that shortcut, so it is impossible to write character "D" in the text-box. Anyone who knows how to solve this problem ?
I tried to override PreviewKeyDown event, also find out which events were fired on pressing key and manipulate them but with no effect.
Here's a quick and dirty example intended to give an idea of how shortcut keys are usually implemented.
Obviously.
This is very simplified and my command doesn't do much.
You can type D into either textbox, no problem.
Markup in mainwindow.
<Window.DataContext>
<local:MainWindowViewModel/>
</Window.DataContext>
<Window.InputBindings>
<KeyBinding Key="D"
Modifiers="Alt"
Command="{Binding MyDcommand}" />
</Window.InputBindings>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Ribbon>
<RibbonGroup>
<TextBox Text="Hello"/>
</RibbonGroup>
</Ribbon>
<TextBox Height="30"
Width="100"
Grid.Row="1"/>
</Grid>
I'm using mvvmlight in the viewmodel so it's easy to define icommands.
using GalaSoft.MvvmLight.CommandWpf;
namespace wpf_99
{
public class MainWindowViewModel : BaseViewModel
{
private RelayCommand myDcommand;
public RelayCommand MyDcommand
{
get
{
return myDcommand
?? (myDcommand = new RelayCommand(
() =>
{
Console.WriteLine("It worked OK");
}
));
}
}
When I press Alt+D the command fires whether the textbox is focussed or not.
The command has scope to the window, rather than just the ribbon. So it works if focus is anywhere in the window.
And I can type a D
is any way to open a web browser(visible?) in specific browser and do action like clic button, search etc. i try
WebBrowser web = new WebBrowser();
web.Navigate(new Uri("https://www.google.com/"));
but i didnt see it. I too know i can do something like that
System.Diagnostics.Process.Start("chrome.exe","http://www.google.com");
but how then make action there control it? Or the only way is open browse in wpf and show it on some king of window.
The best place to actually start learning how to utilize the different Class Controls at our disposal from the .NET environment is reading their documentation!
WebBrowserClass
They show a relative simple example of how to achieve what you want, with the creation of the webbrowser in XAML. In this XAML, they define a TextBox so you can introduce your absolute path, but also a button to perform the search when you click on it.
<Grid x:Name="MainGrid">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<TextBox x:Name="addressTextBox" Width="200" />
<Button Click="Button_Click">Go</Button>
</StackPanel>
<WebBrowser Grid.Row="1" x:Name="myWebBrowser" />
</Grid>
I changed the XAML part a bit, so you don't have your WebBrowser with limited Height and instead have it occupied most of the screen real estate.
PS. In all honesty i cannot pinpoint why your code-behind implementation on the WebBrowser is not working though.
I am very new to WPF and this is my 1st application.
I have a Ribbon with different buttons. I want to load a UserControl based on which button is clicked.
I have a button called "Change Password" and I created the UserControl that will represent the UI to change the password.
I have another button called "Unlock Account" and I have a UserControl that can unlock an account.
App --> Ribbon --> RibbonButton --> SwappableUserControlAtRunTime
I want to use the same space in my Window to load/unload UserControls based on whats clicked.
I am using WPF 4.5 and .Net 4.5 on Windows 8.1
I am targeting PC's with .Net 4.5 and Windows 7+
You can load the UserControls in the ContentControl. Refer below code.
<RibbonWindow x:Class="LayoutWPF_Learning.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Ribbon Grid.Row="0">
<RibbonTab Header="Load UC">
<StackPanel Orientation="Horizontal">
<Button Content="UserControl1" Click="Button_Click"/>
<Button Content="UserControl2" Click="Button_Click_1"/>
</StackPanel>
</RibbonTab>
</Ribbon>
<ContentControl Grid.Row="1" x:Name="cntCtrl" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch"/>
</Grid>
public partial class MainWindow : RibbonWindow
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
cntCtrl.Content = new UserControl1();
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
cntCtrl.Content = new UserControl2();
}
}
Even though you're going with codebehind (I'd recommend you look into MVVM) you'll be able to use a Converter to do this, this is more the WPF way of working than altering controls at runtime from your C# code.
There'll be loads of examples of how to use converters; Google "WPF Converter". Here's one that's relevant to your requirement: http://www.codeproject.com/Tips/285358/All-purpose-Boolean-to-Visibility-Converter
I'm building a SL4 app. I have two controls, a top search bar and a bottom favorites bar, that I'd like to be present on every page. I'm not sure what the best way to do this is.
My current approach uses a nav frame as the root visual:
App.xaml.cs:
this.RootVisual = new NavFrame();
NevFrame.xaml:
<Grid x:Name="LayoutRoot" Background="White">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<my:TopSearchBar x:Name="topSearchBar" Grid.Row="0"/>
<navigation:Frame x:Name="navigationFrame" Source="/HomePage.xaml" Grid.Row="1"/>
<my:BottomFavoritesBar x:Name="bottomFavoritesBar" Grid.Row="2"/>
</Grid>
Then, I'd change pages within the Frame, leaving the persistent elements in place. Is this the correct approach, or is there some other preferred pattern?
However, if I do this, I'm not sure how to let the TopSearchBar and BottomFavoritesBar user controls do navigation. (In general, I'm not sure how to do navigation directly from a UserControl.)
When TopSearchBar was a member of each page, I'd have this code on each page's code-behind:
topSearchBar.ParentPage = this;
TopSearchBar could then use this reference to do navigation:
ParentPage.NavigationService.Navigate(new Uri("/SearchPage.xaml?q=" + searchBox.Text, UriKind.Relative));
Is there a better way to do this? It feels somewhat awkward. If navigation requires a reference to a page, how can I pass that reference from NavFrame?
The appropriate approach is to add a dependency property to both the TopSearchBar and BottomFavoritesBar called "Navigator" (or whatever you prefer) that has the type INavigate.
Your xaml would look like this:-
<Grid x:Name="LayoutRoot" Background="White">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<my:TopSearchBar x:Name="topSearchBar" Grid.Row="0" Navigator="{Binding ElementName=navigationFrame}"/>
<navigation:Frame x:Name="navigationFrame" Source="/HomePage.xaml" Grid.Row="1"/>
<my:BottomFavoritesBar x:Name="bottomFavoritesBar" Grid.Row="2" Navigator="{Binding ElementName=navigationFrame}" />
</Grid>
Now in your two Bar user controls navigation is simply:-
Navigator.Navigate(new Uri("/SearchPage.xaml?q=" + searchBox.Text, UriKind.Relative));
Edit
To create the dependency properties add this to your TopSearchBar class:-
public INavigate Navigator
{
get { return GetValue(NavigatorProperty) as INavigate; }
set { SetValue(NavigatorProperty, value); }
}
public static readonly DependencyProperty NavigatorProperty =
DependencyProperty.Register(
"Navigator",
typeof(INavigate),
typeof(TopSearchBar),
new PropertyMetadata(null));
Duplicate this in your BottomFavoritesBar class but change the reference to TopSearchBar.
I suggest looking in to Prism CAL Pattern
This way you can create regions for your containers and the region(s) you want changed from page to page... it's simple, you just swap the new one to replace the old one while the others remain in place. It's a much more streamlined approach in my opinion.
http://development-guides.silverbaylabs.org/Video/Silverlight-Prism
First I've created a WPF application, then I added new RibbonWindows to the application, and called it RibbonWindow1. Now I want to set the content of the ribbon control via the code belowe and show the ribbon:
RibbonWindow1 ribWindow = new RibbonWindow1
{
Title = "This is a ribbon window",
Content = new UserControl1()
};
ribWindow.ShowDialog();
But I can't see the ribbon bar. If I remove content the ribbon will be shown, also if I use drag and drop I can show it, but I want to do it via simple code, dynamically.
If I can dock the related control in a specific grid cell it will be helpful to me. Any suggestions?
In my little experience with RibbonWindow, i saw that ribbon is part of the content of the ribbonwindow itself. So, a solution could be to expose a public method for the ribbon window that set your usercontrol, like this:
<ribbon:RibbonWindow ...>
<Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ribbon:Ribbon x:Name="Ribbon" />
//add a container for your usercontrol
<Grid Name="contentPlaceHolder" Grid.Row="1"></Grid>
</Grid>
and in the code you can set a method like
public void SetControl(UserControl uc)
{
this.contentPlaceHolder.Content = uc;
}