I'm trying to add a button to the title bar. My XAML looks like the following:
<Page
x:Class="FullScreen.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:FullScreen"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid x:Name="TitleBar">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Application Name" VerticalAlignment="Center"/>
<Button Grid.Column="1" Content="Test" Click="Button_Click"/>
</Grid>
</Grid>
<Grid Grid.Row="1">
<TextBlock>Content</TextBlock>
</Grid>
</Grid>
</Page>
The .cs page has this code:
using System;
using Windows.ApplicationModel.Core;
using Windows.UI.Popups;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
namespace FullScreen
{
public sealed partial class MainPage : Page
{
public MainPage()
{
InitializeComponent();
CoreApplication.GetCurrentView().TitleBar.ExtendViewIntoTitleBar = true;
Window.Current.SetTitleBar(TitleBar);
}
private async void Button_Click(object sender, RoutedEventArgs e)
{
await new MessageDialog("Click!").ShowAsync();
}
}
}
The button shows up but it doesn't respond to the click event. If I comment out the two lines in the constructor:
public MainPage()
{
InitializeComponent();
//CoreApplication.GetCurrentView().TitleBar.ExtendViewIntoTitleBar = true;
//Window.Current.SetTitleBar(TitleBar);
}
The button is in the main body of the app and the click event works correctly. What am I missing?
Thanx,
I'm trying to add a button to the title bar. The button shows up but it doesn't respond to the click event.
According to the official documentation(Remarks part of Window.SetTitleBar), this behavior is by design.
Input
When you call this method to set a XAML UIElement as the title bar, it lets Windows handle input to the title bar UIElement the same way it handles input to the default system title bar. For example, a user can move the window by dragging the XAML UIElement, or invoke the window context menu by right-clicking it.
This means that your app no longer receives pointer input when the user interacts with the target UIElement or its children using touch, mouse, or pen. However, you must still handle (or prevent) keyboard input, and determine whether content in the title bar can receive focus by tabbing to it with the keyboard.
In order to make the button within the title bar to respond to the click event, we can add a rectangle for the customizing title bar in xaml page first:
<Grid x:Name="TitleBar">
<!--Add a rectangle here-->
<Rectangle x:Name="BackgroundElement" />
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Application Name" VerticalAlignment="Center" />
<Button Grid.Column="1" Content="Test" Click="Button_Click" />
</Grid>
</Grid>
Then, set the title bar to the rectangle instead of the entire grid in code behind:
public MainPage()
{
InitializeComponent();
CoreApplication.GetCurrentView().TitleBar.ExtendViewIntoTitleBar = true;
// Set TitleBar to BackgroundElement instead of the entire grid
// Clicks on the BackgroundElement will be treated as clicks on the title bar.
Window.Current.SetTitleBar(BackgroundElement);
}
Here is the official Title bar sample for your reference, and following is the output for the test code above:
Related
I'm developing a UI with the WPF framework and MVVM.
This is the grid while loading:
image of the grid while displaying
This is the UI after the rendering has finished:
image of the grid when rendering is finished
So, as an example, the 3rd column isn't active and will collapse. But the user can see the whole building off the UI in the mainwindow.
Every view I've got is depending on the viewmodel. But also the controls got their own viewmodel. When I take my information together in one control, WPF is getting the information and draws the whole control, for example my tablecontrol. It´s a selfmade control, that is taking data and displays the data in a grid. Because it's one control, the whole grid is loaded in the background and displayed at once. When I make my own grid, because my tablecontrol can't handle the data, every control in the grid is displayed one after one and the grid is slowly displayed on the mainwindow.
<Grid HorizontalAlignment="Left">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
.
.
.
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
.
.
.
</Grid.RowDefinitions>
<unitControls:Label Grid.Row="1" Grid.Column="0" Text="{Binding xx}"/>
<unitControls:Label Grid.Row="1" Grid.Column="1" Text="{Binding xx}"/>
<unitControls:Label Grid.Row="1" Grid.Column="2" Text="{Binding xx}"/>
.
.
.
<unitControls:Label Grid.Row="7" Grid.Column="7" Text="{Binding xx}"/>
<unitControls:Label Grid.Row="7" Grid.Column="8" Text="{Binding xx}"/>
<unitControls:Label Grid.Row="7" Grid.Column="9" Text="{Binding xx}"/>
<Grid>
Is there a way to display the whole content in one view at once? I tried to manipulate the dispatcher in the viewmodel, but nothing helped.
Try something like this:
XAML
<Window x:Class="Example.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">
<DockPanel>
<Button Content="Collect data" Click="OnCollectData" DockPanel.Dock="Top"/>
<ContentControl x:Name="HostControl"/>
</DockPanel>
</Window>
CS
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private async void OnCollectData(object sender, RoutedEventArgs e)
{
var data = await CollectDataAsync();
HostControl.Content = new MyCustomGridControl(data);
}
private async Task<GridDataHolder> CollectDataAsync()
{
GridDataHolder result = null;
await Task.Run(() =>
{
// Collect the logical data on the thread pool
result = GetGridData();
});
return result;
}
}
You can put the HostControl with a ProgressBar in a Grid and play with the Visibility property of the ProgressBar to improve the user experience.
I want to use drawer layout in my app for hamburger but since my app have more than 30 pages having the drawer template declared on each page is not feasible hence I wanted to have the drawer layout as master page with a child/content page inside for which I have written below code with frame tag to navigate to page on click of menu in drawer layout.
Below is my XAML
<Grid x:Name="Rootlayout">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!-- title bar-->
<Grid x:Name="TitleBar" Height="50" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Background="SkyBlue">
<Image Source="/Assets/fs-logo.png" Height="50" HorizontalAlignment="Left" Margin="10,0,0,0"/>
</Grid>
<!--Drawer Layout-->
<drawer:DrawerLayout x:Name="DrawerLayout" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2">
<Grid>
<Frame x:Name="contentFrame" />
</Grid>
<Grid x:Name="listFragment" FlowDirection="LeftToRight" >
<ListView x:Name="listItem" SelectionChanged="listItem_SelectionChanged">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" FontSize="20" Foreground="Black" Margin="10" VerticalAlignment="Center" HorizontalAlignment="Left"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</drawer:DrawerLayout>
</Grid>
While the behavior is exactly as I want but there is problem with hardware back button as when it's pressed the application gets exit. Even I have handle back button press event using following code is app.xaml.cs
//Below code of line in app constructor & it's method defination
#if WINDOWS_PHONE_APP
HardwareButtons.BackPressed += HardwareButtons_BackPressed;
#endif
#if WINDOWS_PHONE_APP
void HardwareButtons_BackPressed(object sender, Windows.Phone.UI.Input.BackPressedEventArgs e)
{
Frame rootFrame = Window.Current.Content as Frame;
if (frame != null && frame.CanGoBack)
{
frame.GoBack();
e.Handled = true;
}
}
#endif
Can anyone help me how to resolve this issue of back button or is there any other way i can utilize drawer layout by which I don't have to write the drawer layout xaml code on each page. One way is using usercontrol but since the content grid is part of drawerlayout I'm not able to figure out how to club my usercontrol & my normal page xaml. Please help thanx in advance
You are checking CanGoBack on the wrong frame.
The Window.Current.Content is your base frame containing the DrawerLayout. What you actually want to address is the contentFrame inside of it.
So what you really want to look at is:
(Window.Current.Content as RootPage)?.Frame.CanGoBack
Where RootPage is the name of your Page for the Xaml you posted in your question.
I tried to create a modal UserControl because the ContentDialog control is difficult to modify.
How to change background overlay of ContentDialog uwp
The title zone will be on the content zone(like a ContentDialog) but the background should be the same as the owerlay content.
What i try to do
How should i do to create this modal UserControl?
EDIT:
Thanks for your answer!
Actualy i have my control
<UserControl x:Class="TestModal.ModalView">
<Grid Background="Black" Opacity="0.5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock Text="test"/>
</Grid>
</UserControl>
A main page :
Xaml
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Button Click="Show_Click" />
</Grid>
</Page>
C#:
private void Show_Click(object sender, RoutedEventArgs e)
{
ModalView myModalView = new ModalView();
Content = myModalView;
}
But how can i activate the user control? change content is not what i want to do.
You can easily create a control with an Grid for instance overlaying the complete UI. Give that grid for instance a black color with opacity 0.6 so you can see the underlying UI. Then just fill the Grid with controls you want to show. On events like 'click outside of the data area' (silent dismiss) or clicking a button ('close' or 'save' for instance) you can hide the UI again. And this can be packaged in a UserControl that can be used on other Pages.
If this is an answer to your question, please mark this as answer.
Is there chance to create a WPF Popup as a separate control, so it is not inside a window or user control?
I have a popup written in XAML:
<Popup PopupAnimation="Fade" Name="MyPopup" MinWidth="200" MinHeight="100" Width="200" Height="100" Placement="Center" VerticalAlignment="Center" HorizontalAlignment="Center" IsEnabled="True" IsOpen="False">
<Grid Width="Auto" Height="Auto" Background="Gray">
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Border BorderThickness="2" CornerRadius="8" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.RowSpan="2">
<Border.BorderBrush>
<SolidColorBrush Color="Gray"/>
</Border.BorderBrush>
<Border.Background>
<SolidColorBrush Color="White"/>
</Border.Background>
</Border>
<StackPanel Grid.Row="0">
<Label Foreground="Blue" Content="Popup_Title"/>
</StackPanel>
<GroupBox Grid.Row="1" Header="Popup example content">
<StackPanel>
</StackPanel>
</GroupBox>
</Grid>
</Popup>
Now, on button click of my other control, I would like to do something like this:
private void Button_Click(object sender, RoutedEventArgs e)
{
PopupControl p = new PopupControl();
p.IsOpen = true;
}
By looking at the example of UserControl or Window, I understand that I need to connect this popup with the actual c# class, something like:
public partial class PopupControl : Popup
{
public PopupControl()
{
InitializeComponent();
}
}
and then inside the Popup's XAML add class:
x:Class="WpfApplication1.PopupControl".
but two things:
1) There is no such a thing as x:Class for PopUp
2) Deriving from Popup won't have InitializeComponent(); method.
You almost got it right. While copy-pasting your Popup code in its own XAML file, you didn't add the necessary x namespace that contains the attached property x:Class:
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
As soon as you add this to your root element (Popup), you can add x:Class="WpfApplication1.PopupControl". This will lead to the generation of a partial class in your obj folder that contains the InitializeComponent method that you were missing.
The easiest way to do that is by
creating a new UserControl from the "Add Item" dialog.
Then, rename the root element from UserControl to Popup.
Finally, from the code behind class, just remove : UserControl.
i have a problem , i have 2 uc that displayed in main windows.
i want when i press on button in the first uc the text in the other uc will change
this the axml i use and the code
first uc
<Grid.RowDefinitions>
<RowDefinition ></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Button Width="40" Height="40" Name="playbtn" HorizontalAlignment="Left" Grid.Row="0" Grid.Column="0" Click="playbtn_Click" >
<Button.Content>
<Image Source="/img/player_play.png" ></Image>
</Button.Content>
</Button>
<Button Width="40" Height="40" Name="pausebtn" Grid.Column="1" Grid.Row="0" >
<Button.Content>
<Image Source="/img/player_pause.png" ></Image>
</Button.Content>
</Button>
<Button Width="40" Height="40" Name="stopbtn" Grid.Column="2" Grid.Row="0" >
<Button.Content>
<Image Source="/img/player_stop.png" ></Image>
</Button.Content>
</Button>
</Grid>
</StackPanel>
</Grid>
</StackPanel>
secound uc <TextBlock Name="Progresstimertext" Text="00:00:00" FontSize="20"></TextBlock>
so i want to press on start button and the timer will be change? how to
10x
This should be managed in the View Model of your Main Window, as this seems the only location that has knowledge of both controls and it sounds as though each of your user control's shouldn't necessarily have knowledge of each other.
Ideally, you should have a reference to each of your user controls in the code-behind (or view model class is you have a dedicated one).
If in code behind, you would simply expose these by giving them names.
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="your controls reference here">
<Grid>
<Grid.ColumnDefinitions>
</ColumnDefinition>
</ColumnDefinition>
</Grid.ColumnDefinitions>
<controls:UserControl1 x:Name="Control1"/>
<controls:UserControl2 x:Name="Control2" Grid.Column="1"/>
</Grid>
</Window>
Now you can reference them in your code behind by name Control1 and Control2. These user control classes should be exposing the properties that you want to control, in your case ProgressTimerText, such that, in the code-behind, you can set it easily such as
Control2.ProgressTimerText = "00:00:00";
Where to do this? Well you probably want to create a Stopped event on your Control1, that you can attach to your code behind - in your case, something like Stopped. In your UserControl1 class you should declare something like
public event EventHandler Stopped;
And then in the local event handler for the Click of the stop button, invoke that event.
private void Stop_Click(object sender, RoutedEventArgs e)
{
if (Stopped != null)
Stopped(this, e);
}
Attach that in your MainWindow:
<controls:UserControl1 x:Name="Control1" Stopped=Control1_Stopped/>
Now in your code-behind you should have something like:
private void Control1_Stopped(object sender, RoutedEventArgs e)
{
Control2.ProgressTimerText = "00:00:00";
}