I am building a WPF app using NavigationWindow with many Pages. I have created popups within a Page like follows:
XAML
<Popup PlacementTarget="{Binding ElementName=mainDisplay}" Placement="Center" Name="myPopup">
<Frame Name="popupFrame"/>
</Popup>
codebehind
popupFrame.Navigate(new MyUserControl()); //navigate to a user control
myPopup.IsOpen = true; //to "pop up" popup
Except now, I would like a "global" popup, which is based on a timer and can popup at any page when time is up. The timer is inside the main NavigationWindow's codebehind and keeps ticking across all pages, but I cannot place the popup directly within the NavigationWindow since it does not support direct content. How can i achieve this?
Thanks in advance!
As it turns out, it's very simple. I just need to create a popup in codebhind of NavigationWindow, and set myPopup.IsOpen=true when time is up.
Related
I currently have a program where you can load a text in it.
Now I created a button that Pops up a flyout/ContentDialog but Im not happy with it because Limits me of what Im trying to achieve.
When I click the button it opens a flyout, the flyout gets the full Focus. That means I cannot scroll to the text WHILE the flyout-box is open. And if I click outside the flyout-box the flyout-box disappears.
I have a similar Problem to the ContentDialog.
When I click the button and the ContentDialog Pops up, everything behind the ContentDialog goes a bit into White/Grey Color. Also the ContentDialog does not allow any Focus outside the ContentDialog itself.
So what do I want to have?
I want that when I click on the button that a Window appears. I should be able to customize the window (writing text in it and it should have a button).
While this Window is open I want to be able to do Actions outside that window without the window Closing. For example Scrolling through the text I loaded.
Is there something I can achieve this with?
Take a look at the Popup class. This will let you display content on top of other content within your app's window. It's similar to the Flyout but without all of the built-in Flyout behavior that you don't want. The Popup class documentation has more details and commentary on when and how to use it.
Here's a really bland example with no styling.
<Grid>
<Popup x:Name="popup">
<StackPanel>
<TextBlock Text="Poppity pop pop" />
<Button Click="ClosePopup_Click">Close</Button>
</StackPanel>
</Popup>
<Button Click="OpenPopup_Click">Open Popup</Button>
</Grid>
private void OpenPopup_Click(object sender, RoutedEventArgs e)
{
popup.IsOpen = true;
}
private void ClosePopup_Click(object sender, RoutedEventArgs e)
{
popup.IsOpen = false;
}
There is a slightly more complicated example in the Popup documentation
I just hide and show grids with whatever I want inside.
Is there a way to disable dropping items like notepad, word etc on to a System.Windows.Controls.WebBrowser control in WPF.
I have tried various options like
AllowDrop="False" - Does not work.
Tried to catch events like Drop, PreviewDrop, DragLeave, PreviewDragLeave, PreviewDragOver, PreviewDragEnter - None of these events fire when I drop items on the WebBrowser control.
Using the constructor or Xaml to create the following method will stop the drag from changing the webbrowsers current state:
private void webBrowser_Navigating(object sender, NavigatingCancelEventArgs e)
{
// The WebBrowser control is checking the Uri
if (e.Uri.ToString() != "Place your url string here") //ex: "http://stackoverflow.com"
{
// Uri is not the same so it cancels the process
e.Cancel = true;
}
}
As you mentioned, none of the Drop event are fired, and it seems like the native browser control is very limited which leaves you with two possibilities:
Either user another browser control like wpfchromium,
Or define a transparent popup in top of the browser and handle
the drop even within it
:
<WebBrowser Height="300" Width="300" x:Name="wbBrowser"/>
<Popup Opacity="1" AllowsTransparency="True" IsOpen="True" Placement="Center"
PlacementTarget="{Binding ElementName=wbBrowser}" >
<Border Background="Black" Opacity="0.01"
Width="300" Height="300">
</Border>
</Popup>
This solution ain't pretty at all and needs also more logic to handle when the popup's parent control moves..
...you may also find this solution helpful, if your main content is html:
How to disable drop on wpf webbrowser control
I am having a problem with a page in my Windows 8.1 Store App that is taking a long time to render - it is a grid with a number of columns and rows that gets bound to data on loading of the page.
It is not the loading of the data that is slow but the actual binding of the data to the grid.
I ideally want to display a dialog bar to indicate to the user that something is loading and they have clicked on the previous navigate button okay.
I saw someone mention the possibility of having a "loading page" which only has a progress bar in it - and I thought this solution might work but I can't work out in what event of the loading page should I navigate to the actual page.
i.e.
User clicks button which calls
this.Frame.Navigate(typeof(LoadingPage));
Loading Page displays a progress bar
I know need to be able to call
this.Frame.Navigate(typeof(ActualPage));
The user sees the progress bar whilst ActualPage loads.
Any suggestions would be greatly appreciated thanks!
Thanks to the support team at DEVExpress I have a solution to my problem.
Firstly on the page that takes time to load I have wrapped my Grid in a ContentControl
<ContentControl Visibility="Collapsed" Name="Content">
<!-- Grid in here -->
</ContentControl>
I then added a TextBlock which I will use as to display "Loading..." to my page. I have called this control indicator.
<TextBlock x:Name="indicator" Text="Loading..." />
I have attached the following method to the Loaded event of the page which uses a timer
void MainPage_Loaded(object sender, RoutedEventArgs e)
{
indicator.Visibility = Windows.UI.Xaml.Visibility.Visible;
DispatcherTimer t = new DispatcherTimer { Interval = TimeSpan.FromSeconds(1) };
t.Tick += (dd, ee) =>
{
t.Stop();
Content.Visibility = Windows.UI.Xaml.Visibility.Visible;
};
t.Start();
}
Then when the gridcontrol has Loaded I hide the indicator TextBlock
void gridControl_Loaded(object sender, RoutedEventArgs e)
{
indicator.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
}
This works perfectly for me. I can't use the Windows 8 ProgressBar control because the animation is loaded on the same thread that loads the grid - but I am happy enough to have any indicator.
Also thanks Brian Stump for pointing me in the right direction.
First, I will suggest using a ListView or GridView to display your databound objects because of build-in UI virtualization.
However, maybe this will work for your situation.
Do you know when your page is ready to display? If so, place a progress ring in front of your grid while it loads in the background.
<Grid x:Name="FullPageGrid">
<Grid x:Name="YourGridContent">
</Grid>
<Grid Background="White" Visibility="Visible" x:Name="ProgressRingGrid">
<ProgressRing IsActive="True"></ProgressRing>
</Grid>
</Grid>
When the data is fully loaded, change the visibility of the "ProgressRingGrid" to Visibility="Collapsed"
I am currently writing a desktop application, but I cannot seem to get my head around what to use when redirecting someone to a new section of the application.
My options appear to be
Window
Page
UserControl
but I don't understand what the difference between them is, and when I should use each one.
Could someone explain the differences for me, and give an example of what situations/applications you may use each one for?
A Window object is just what it sounds like: its a new Window for your application. You should use it when you want to pop up an entirely new window. I don't often use more than one Window in WPF because I prefer to put dynamic content in my main Window that changes based on user action.
A Page is a page inside your Window. It is mostly used for web-based systems like an XBAP, where you have a single browser window and different pages can be hosted in that window. It can also be used in Navigation Applications like sellmeadog said.
A UserControl is a reusable user-created control that you can add to your UI the same way you would add any other control. Usually I create a UserControl when I want to build in some custom functionality (for example, a CalendarControl), or when I have a large amount of related XAML code, such as a View when using the MVVM design pattern.
When navigating between windows, you could simply create a new Window object and show it
var NewWindow = new MyWindow();
newWindow.Show();
but like I said at the beginning of this answer, I prefer not to manage multiple windows if possible.
My preferred method of navigation is to create some dynamic content area using a ContentControl, and populate that with a UserControl containing whatever the current view is.
<Window x:Class="MyNamespace.MainWindow" ...>
<DockPanel>
<ContentControl x:Name="ContentArea" />
</DockPanel>
</Window>
and in your navigate event you can simply set it using
ContentArea.Content = new MyUserControl();
But if you're working with WPF, I'd highly recommend the MVVM design pattern. I have a very basic example on my blog that illustrates how you'd navigate using MVVM, using this pattern:
<Window x:Class="SimpleMVVMExample.ApplicationView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SimpleMVVMExample"
Title="Simple MVVM Example" Height="350" Width="525">
<Window.Resources>
<DataTemplate DataType="{x:Type local:HomeViewModel}">
<local:HomeView /> <!-- This is a UserControl -->
</DataTemplate>
<DataTemplate DataType="{x:Type local:ProductsViewModel}">
<local:ProductsView /> <!-- This is a UserControl -->
</DataTemplate>
</Window.Resources>
<DockPanel>
<!-- Navigation Buttons -->
<Border DockPanel.Dock="Left" BorderBrush="Black"
BorderThickness="0,0,1,0">
<ItemsControl ItemsSource="{Binding PageViewModels}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content="{Binding Name}"
Command="{Binding DataContext.ChangePageCommand,
RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
CommandParameter="{Binding }"
Margin="2,5"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Border>
<!-- Content Area -->
<ContentControl Content="{Binding CurrentPageViewModel}" />
</DockPanel>
</Window>
Window is like Windows.Forms.Form, so just a new window
Page is, according to online documentation:
Encapsulates a page of content that can be navigated to
and hosted by Windows Internet Explorer, NavigationWindow, and Frame.
So you basically use this if going you visualize some HTML content
UserControl is for cases when you want to create some reusable component (but not standalone one) to use it in multiple different Windows
All depends on the app you're trying to build. Use Windows if you're building a dialog based app. Use Pages if you're building a navigation based app. UserControls will be useful regardless of the direction you go as you can use them in both Windows and Pages.
A good place to start exploring is here: http://windowsclient.net/learn
We usually use One Main Window for the application and other windows can be used in situations like when you need popups because instead of using popup controls in XAML which are not visible we can use a Window that is visible at design time so that'll be easy to work with
on the other hand we use many pages to navigate from one screen to another like User management screen to Order Screen etc In the main Window we can use Frame control for navigation like below
XAML
<Frame Name="mainWinFrame" NavigationUIVisibility="Hidden" ButtonBase.Click="mainWinFrame_Click">
</Frame>
C#
private void mainWinFrame_Click(object sender, RoutedEventArgs e)
{
try
{
if (e.OriginalSource is Button)
{
Button btn = (Button)e.OriginalSource;
if ((btn.CommandParameter != null) && (btn.CommandParameter.Equals("Order")))
{
mainWinFrame.Navigate(OrderPage);
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error");
}
}
That's one way of doing it We can also use a Tab Control instead of Fram and Add pages to it using a Dictionary while adding new page check if the control already exists then only navigate otherwise add and navigate. I hope that'll help someone
Most of all has posted correct answer. I would like to add few links, so that you can refer to them and have clear and better ideas about the same:
UserControl:
http://msdn.microsoft.com/en-IN/library/a6h7e207(v=vs.71).aspx
The difference between page and window with respect to WPF:
Page vs Window in WPF?
In SL4, I am finding it oddly difficult to figure out how to make a HyperlinkButton navigate to another Silverlight page in the same application when clicked. The structure is:
<HyperlinkButton Content="Technical Information Screen" Height="23"
Name="hyperlinkButton1" Width="320" NavigateUri="/tis.xaml" />
"tis.xaml" is in the same folder as MainPage.xaml, which is where this button is located. When clicked, the button raises "404 Not Found".
If I change to having the NavigateUri get filled programmatically in the MainPage constructor, as in:
hyperlinkButton1.NavigateUri = new Uri("/tis.xaml", UriKind.Relative);
I get the same result, as I do with not decorating with "/", and with UriKind set to Absolute or RelativeOrAbsolute. It is all very mysterious, but I know it must be do-able somehow, or why have the control at all?
Hyperlink button's default behavior is to point the browser to a different page (i.e. a whole other HTML page).
Navigation between XAML pages within the same application is explained in detail here (I suppose you will have to call NavigationService.Navigate() in the click event of the hyperlink button).
You need to set the HyperlinkButton's TargetName property to the Name of the navigation:Frame control which you want to fill in with the new page. Condensing it down to essentials:
<UserControl ...
xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation">
<Grid>
<HyperlinkButton Content="Technical Information Screen" NavigateUri="/tis.xaml" TargetName="ContentFrame"/>
<navigation:Frame x:Name="ContentFrame"/>
</Grid>
</UserControl>
Most likely the issue is with the uri format, try pointing to the aspx page hosting the silverlight control.
hyperlinkButton1.NavigateUri = new Uri("http://foo.page.aspx");