I downloaded the Microsoft Visual Studio 2010 Express for Windows Phone and I wrote a simple application to make a first test of the emulator. In this application I have only a button with the property Content binded to a string called ButtonText and with the property Background binded to a SolidColorBrush named FillColor. I handled the Click event with this code:
void MyButton_Click(object sender, RoutedEventArgs e)
{
if (toggle == true)
{
ButtonText = "Blue";
FillColor = new SolidColorBrush(Colors.Blue);
}
else
{
ButtonText = "Red";
FillColor = new SolidColorBrush(Colors.Red);
}
toggle = !toggle;
}
Unfortunately this doesn't work. While the Content of the Button changes each time the button is pressed, I cannot say the same for the Background which remains at the same color.
Could you tell me what is wrong? Thank you.
I also post the XAML:
<Grid x:Name="ContentGrid" Grid.Row="1">
<Button Name="MyButton" Width="300" Height="300"
Content="{Binding Path=ButtonText}"
Background="{Binding Path=FillColor}" />
</Grid>
The issue is with the use of "new" in the line:
FillColor = new SolidColorBrush(Colors.Blue);
Using the "new" operation breaks the data binding that was previously set up. Try using the following instead:
FillColor.Color = Colors.Blue;
Replace both the changes to Blue and to Red and that should do the trick.
HTH!
Chris
Related
I want to view TabView in title bar like image below.
I'm using UWP WinUI 2.
I'm trying to view my TabView in title bar. But TabView is viewing under title bar.
My MainPage.xaml code:
<muxc:TabView Grid.Row="2">
<muxc:TabViewItem Header="New Tab">
</muxc:TabViewItem>
</muxc:TabView>
This is actually pretty easy:
In your xaml code:
This piece of code adds a ShellTitlebarInset and a CustomDragRegion to the TabView. This is needed, to add a margin to the left and right side of the window.
<muxc:TabView x:Name="tabView">
<muxc:TabView.TabStripHeader>
<Grid x:Name="ShellTitlebarInset" Background="Transparent" />
</muxc:TabView.TabStripHeader>
<muxc:TabView.TabStripFooter>
<Grid x:Name="CustomDragRegion" MinWidth="188" Loaded="CustomDragRegion_Loaded" Background="Transparent" />
</muxc:TabView.TabStripFooter>
<muxc:TabViewItem Header="Tab1"/>
<muxc:TabViewItem Header="Tab2"/>
<muxc:TabViewItem Header="Tab3"/>
</muxc:TabView>
In your MainPage:
The LayoutMetricsChanged event handles the FlowDirection either from LeftToRight or RightToLeft to add the specific margin to the CustomDragRegion and ShellTitlebarInset.
private void CoreTitleBar_LayoutMetricsChanged(CoreApplicationViewTitleBar sender, object args)
{
if (FlowDirection == FlowDirection.LeftToRight)
{
CustomDragRegion.MinWidth = sender.SystemOverlayRightInset;
ShellTitlebarInset.MinWidth = sender.SystemOverlayLeftInset;
}
else
{
CustomDragRegion.MinWidth = sender.SystemOverlayLeftInset;
ShellTitlebarInset.MinWidth = sender.SystemOverlayRightInset;
}
CustomDragRegion.Height = ShellTitlebarInset.Height = sender.Height;
}
//Make sure to extend the view after the CustomDragRegion loaded, otherwise the tabs may clip under the minimize, maximize and close buttons of the window:
private void CustomDragRegion_Loaded(object sender, RoutedEventArgs e)
{
var coreTitleBar = CoreApplication.GetCurrentView().TitleBar;
coreTitleBar.ExtendViewIntoTitleBar = true;
coreTitleBar.LayoutMetricsChanged += CoreTitleBar_LayoutMetricsChanged;
Window.Current.SetTitleBar(CustomDragRegion);
}
Here also the official documentation from Microsoft:
https://learn.microsoft.com/en-us/windows/apps/design/controls/tab-view
I wonder is there an API for creating custom notifications in Windows 10 style like the one showing when updates are available for example?
I know that Citrix can send messages showing like that and it seems they use the sessionmsg.exe. Unfortunately, I cannot find any help on the parameter the exe supports.
Also, an API would be preferred.
Another thing: How do you call this kind of message? Banner? Message? MessageBox? SystemMessage?
After reading the question, I found it interesting my selves to investigate possibilities and share my founds as the answer.
As you tagged your question with C#, my solution will be based on C#. By and btw I was not able to find the default api to do the job, if other finds a solution with an example I will be happy to vote for it.
I started with the UWP solution and created a very simple information dialog using ContentDialog. Create a UWP project and add the following code:
private async void ShowMessage()
{
ContentDialog dialog = new ContentDialog
{
Title = "Title",
Content = "Content text",
Width = 200,
Height = 600,
Background = new SolidColorBrush(Colors.CornflowerBlue),
Foreground = new SolidColorBrush(Colors.White),
BorderThickness = new Thickness(1),
BorderBrush = new SolidColorBrush(Colors.White),
CloseButtonText = "Close",
};
await dialog.ShowAsync();
}
public MainPage()
{
this.InitializeComponent();
ShowMessage();
}
This will create something like
But that content dialog appears as a part of the application and not the windows system as I tried to solve.
Adding the following lines before the ShowMessage method will maximize application to the whole background of the screen.
ApplicationView.GetForCurrentView().SuppressSystemOverlays = true;
ApplicationView.GetForCurrentView().FullScreenSystemOverlayMode = FullScreenSystemOverlayMode.Minimal;
ApplicationView.GetForCurrentView().TryEnterFullScreenMode();
But IMO it is not the best solution. I thought, there might be another way, I tried with WPF instead.
I created a WPF project, my strategy was to start MainWindow in minimized mode and the content dialog to appear. Hence there is no content dialog in WPF like UWP, I created something similar (look and feel).
Here is the code in my MainWindow
private readonly string _title;
private readonly string _message;
public MainWindow()
{
_title = "Updates are available";
_message = "Required updates need to be downloaded.";
InitializeComponent();
string[]? args = App.Args;
if (args != null && args.Length > 0)
{
_title = args[0];
_message = args[1];
}
MinimizedMainWindow();
ShowContentDialog();
}
protected void MinimizedMainWindow()
{
AllowsTransparency = true;
WindowStyle = WindowStyle.None;
WindowState = WindowState.Maximized;
Background = Brushes.Transparent;
Topmost = true;
}
public void ShowContentDialog()
{
ContentDialog dialog = new ContentDialog
{
Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FF0066CC")),
Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FFFFFFFF")),
WindowStartupLocation = WindowStartupLocation.CenterScreen,
SizeToContent = SizeToContent.WidthAndHeight,
WindowStyle = WindowStyle.None,
Padding = new Thickness(20),
Margin = new Thickness(0),
ResizeMode = ResizeMode.NoResize,
Width = 600,
Height = 200,
Title = { Text = _title },
Message = { Text = _message }
};
dialog.Show();
}
And here is my ContentDialog.xaml
<Window x:Class="NotificationSol.ContentDialog"
xmlns:local="clr-namespace:NotificationSol"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:av="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
Title="ContentDialog"
av:DesignWidth="600"
av:DesignHeight="200"
>
<Grid>
<TextBlock x:Name="Title" Margin="30,22,30,118" TextWrapping="Wrap" Text="Title" FontSize="28"/>
<TextBlock x:Name="Message" Margin="30,70,30,70" TextWrapping="Wrap" Text="Content" FontSize="16"/>
<Button x:Name="Button" Click="CloseButton_Click" Content="Close" HorizontalAlignment="Right" Margin="0,0,30,20" VerticalAlignment="Bottom" Width="75" Background="#FF0066CC" BorderBrush="White" Foreground="White" Padding="8,4"/>
</Grid>
</Window>
And ContentDialog.xaml.cs
public ContentDialog()
{
InitializeComponent();
}
private void CloseButton_Click(object sender, RoutedEventArgs e)
{
Close();
base.OnClosed(e);
Application.Current.Shutdown();
}
To let my application take parameters in the command line, I made the following changes to App.xaml.cs:
public static string[]? Args;
void AppStartup(object sender, StartupEventArgs e)
{
if (e.Args.Length > 0)
{
Args = e.Args;
}
}
And to App.xaml adding as the startup
<Application x:Class="NotificationSol.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:NotificationSol"
StartupUri="MainWindow.xaml"
Startup="AppStartup">
<Application.Resources>
</Application.Resources>
</Application>
Running this code from the visual studio I get the:
If you run the software with 2 parameters from the command line, you can pass the title and the message. You have the code, where you can create other method actions or buttons with other features. Right now my button is just closing the dialog box and the application. Here I have put both examples on my repo:
https://github.com/maythamfahmi/BlogExamples/tree/master/Stackoverflow/ContentDialog
You need to create a function using Winforms and WPF assemblies to create the pop up.
Functions
Function New-WPFDialog() {
<#
.SYNOPSIS
This neat little function is based on the one from Brian Posey's Article on Powershell GUIs
.DESCRIPTION
I re-factored a bit to return the resulting XaML Reader and controls as a single, named collection.
.PARAMETER XamlData
XamlData - A string containing valid XaML data
.EXAMPLE
$MyForm = New-WPFDialog -XamlData $XaMLData
$MyForm.Exit.Add_Click({...})
$null = $MyForm.UI.Dispatcher.InvokeAsync{$MyForm.UI.ShowDialog()}.Wait()
.NOTES
Place additional notes here.
.LINK
http://www.windowsnetworking.com/articles-tutorials/netgeneral/building-powershell-gui-part2.html
.INPUTS
XamlData - A string containing valid XaML data
.OUTPUTS
a collection of WPF GUI objects.
#>
Param([Parameter(Mandatory = $True, HelpMessage = 'XaML Data defining a GUI', Position = 1)]
[string]$XamlData)
# Add WPF and Windows Forms assemblies
try {
Add-Type -AssemblyName PresentationCore, PresentationFramework, WindowsBase, system.windows.forms
}
catch {
Throw 'Failed to load Windows Presentation Framework assemblies.'
}
# Create an XML Object with the XaML data in it
[xml]$xmlWPF = $XamlData
# Create the XAML reader using a new XML node reader, UI is the only hard-coded object name here
Set-Variable -Name XaMLReader -Value #{ 'UI' = ([Windows.Markup.XamlReader]::Load((new-object -TypeName System.Xml.XmlNodeReader -ArgumentList $xmlWPF))) }
# Create hooks to each named object in the XAML reader
$Elements = $xmlWPF.SelectNodes('//*[#Name]')
ForEach ( $Element in $Elements ) {
$VarName = $Element.Name
$VarValue = $XaMLReader.UI.FindName($Element.Name)
$XaMLReader.Add($VarName, $VarValue)
}
return $XaMLReader
}
Function New-PopUpWindow () {
param(
[string]
$MessageText = "No Message Supplied")
# This is the XaML that defines the GUI.
$WPFXamL = #'
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Popup" Background="#FF0066CC" Foreground="#FFFFFFFF" ResizeMode="NoResize" WindowStartupLocation="CenterScreen" SizeToContent="WidthAndHeight" WindowStyle="None" Padding="20" Margin="0">
<Grid>
<Button Name="OKButton" Content="OK" HorizontalAlignment="Right" Margin="0,0,30,20" VerticalAlignment="Bottom" Width="75" Background="#FF0066CC" BorderBrush="White" Foreground="White" Padding="8,4"/>
<TextBlock Name="Message" Margin="100,60,100,80" TextWrapping="Wrap" Text="_CONTENT_" FontSize="36"/>
</Grid>
</Window>
'#
# Build Dialog
$WPFGui = New-WPFDialog -XamlData $WPFXaml
$WPFGui.Message.Text = $MessageText
$WPFGui.OKButton.Add_Click( { $WPFGui.UI.Close() })
$null = $WPFGUI.UI.Dispatcher.InvokeAsync{ $WPFGui.UI.ShowDialog() }.Wait()
}
Example call and result
New-PopUpWindow -MessageText "Hey there, I'm a pretty blue form"
Interested in that too.
Finished with simple WinForms C# app though I'm not in code. It covers every screen with 50% transparent black fullscreen form and then opens modal (OnShown TopMost) blue borderless 678x165 form from the primary screen form. Picked almost same colors and fonts (Segoe UI title + Calibri text and bold buttons) so it is pretty simple and similar phoney. And I've added second red button with some special functionality, what is of course impossible via standard API.
Another way is to know that such a message can be called with Send-RDUserMessage powershell cmdlet from RemoteDesktop module. I opened the module source code and understood that it uses wtsapi32.dll. I stopped pushing that direction because of:
RemoteDesktop module requires admin elevation, maybe wtsapi calls in general requires that too; but I want banner to launch in user context from task scheduler;
Cast Send-RDUserMessage on Windows 10 desktop OS results in small "msg.exe"-like (not sessionmsg.exe) messagebox but I want that banner on Windows 10 workstations too, not only on terminal servers. But workstations use the same banner to say about updates and activation so it is definitely not server unique function.
I am not into coding at all. Someone can try to get along with that dll, maybe WTSSendMessageA and WTSSendMessageW methods which are documented at learn.microsoft.com. Maybe it calls another API because such messages are not only for RD/TS purposes. But I got tired dealing with it.
Still interested in oneliner :)
I have a Control that is in a WindowsFormsHost. This control is for drawing content in an OpenGL context and need to be invalidated after every draw.
The problem: WPF Controls are not reacting anymore, if I do that. You can click on them and they work, but you do not get any visual feedback like when you hover over it or press the WPF button. The button does not change the color or something it normaly does, if you hover over it.
I created a little repro for you:
XAML
<Grid>
<WindowsFormsHost x:Name="uxContainerWindowsFormsHost" HorizontalAlignment="Left" Height="163" Margin="101,29,0,0" VerticalAlignment="Top" Width="223"/>
<Button Content="Button" HorizontalAlignment="Left" Margin="225,260,0,0" VerticalAlignment="Top" Width="75"/>
</Grid>
Code
public MainWindow()
{
InitializeComponent();
var b = new System.Windows.Forms.Button();
b.BackColor = System.Drawing.Color.Gray;
b.Text = "Button";
b.Paint += b_Paint;
uxContainerWindowsFormsHost.Child = b;
}
void b_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
(sender as System.Windows.Forms.Button).Invalidate();
}
If you click on the WPF button, you will not get any visual feedback that you clicked on the button.
Question
How can I use a continous invalidation in my WindowsFormsHost like in the repro, without loosing the visual feedback on my buttons?
The solution was the CompositionTarget.Rendering event that Dr. ABT showed in the comment.
Constructor()
{
CompositionTarget.Rendering += CompositionTarget_Rendering;
}
void CompositionTarget_Rendering(object sender, EventArgs e)
{
_myControl.Invalidate();
}
I learning WPF and build an simple application.
This is my button:
<Button x:Name="btnAddFiles" Content="Add" HorizontalAlignment="Left" Margin="1046,34,0,0" VerticalAlignment="Top"
Width="111" Height="34" FontSize="20" Foreground="{DynamicResource {x:Static SystemColors.ActiveBorderBrushKey}}"
Background="{x:Null}" MouseEnter="btnAddFiles_MouseEnter" BorderBrush="Transparent" />
And this is how it looks like:
http://s27.postimg.org/h0iq4mrrz/image.png
I have changed the button background color to Transparent so the background color the you see is all my application background color.
All i want to do is when the mouse is over the button change the background color to Transparent.
Currently this is the current when mouse is over:
http://s30.postimg.org/x61ssujnx/image.png?noCache=1411485462
So i registered to MouseEnter event:
private void btnAddFiles_MouseEnter(object sender, MouseEventArgs e)
{
//btnAddFiles.Background = // change the color
}
But i can see that btnAddFiles.Background require Brush and nor Color
Any idea hot to change it ?
i couldn't see your pictures but this is how we change back color in wpf:
btnAddFiles.Background = Brushes.Transparent;
and you can use your code in a mouse enter and mouse leave event.
1st Edit
private void btnAddFiles_MouseEnter(object sender, MouseEventArgs e)
{
btnAddFiles.Background = Brushes.Transparent;
}
private void btnAddFiles_MouseLeave(object sender, MouseEventArgs e)
{
btnAddFiles.Background = Brushes.Lime;
}
2nd Edit:
for changing border color and thickness:
button1.BorderBrush = Brushes.Red;
Thickness t = new Thickness(5, 5, 5, 5);
button1.BorderThickness = t;
also change your margin, it is out form. try for example
Margin="50,50,0,0"
let me know if you get your answer.
I want to create some sort of filter, when user clicks the filter button from the app bar it will fire up a popup page with list picker in it. I've googled and tried quite a number of solutions but still cannot get it to work.
Here are my codes:
XAML (MainPageView.xaml)
<phone:PhoneApplicationPage.Resources>
<DataTemplate x:Key="PivotContentTemplate">
<phone:Pivot Margin="-12,0,0,0" Title="FOREX NEWS" Height="672">
<phone:PivotItem Header="filter" FontFamily="{StaticResource PhoneFontFamilySemiLight}" FontSize="32">
<StackPanel Margin="12,0,0,0">
<toolkit:ListPicker Header="currencies" SelectionMode="Multiple"
micro:Message.Attach="[Event SelectionChanged] = [Action OnCurrenciesChanged($eventArgs)]">
<sys:String>gbp</sys:String>
<sys:String>eur</sys:String>
<sys:String>usd</sys:String>
</toolkit:ListPicker>
</StackPanel>
</phone:PivotItem>
</phone:Pivot>
</DataTemplate>
<phone:PhoneApplicationPage.Resources>
...
Still inside MainPageView.xaml
<bab:BindableAppBar Grid.Row="2" Mode="Minimized">
<bab:BindableAppBarButton micro:Message.Attach="[Event Click] = [Action ShowFilter($view, $eventArgs]">
</bab:BindableAppBarButton>
</bab:BindableAppBar>
MainPageViewModel.cs
public void ShowFilter(object sender, RoutedEventArgs e)
{
var view= sender as MainPageView;
CustomMessageBox messageBox = new CustomMessageBox()
{
ContentTemplate = (DataTemplate)view.Resources["PivotContentTemplate"],
LeftButtonContent = "filter",
RightButtonContent = "cancel",
IsFullScreen = true // Pivots should always be full-screen.
};
messageBox.Dismissed += (s1, e1) =>
{
switch (e1.Result)
{
case CustomMessageBoxResult.LeftButton:
// Do something.
break;
case CustomMessageBoxResult.RightButton:
// Do something.
break;
case CustomMessageBoxResult.None:
// Do something.
break;
default:
break;
}
};
messageBox.Show();
}
public void OnCurrenciesChanged(SelectionChangedEventArgs e)
{
}
For your information, I am using Caliburn.Micro and WP Toolkit for the CustomMessageBox and ListPicker.
I received exception No target found for method OnCurrenciesChanged. I only receive the exception when I after I select few items in the list picker and click any of the buttons to save the change. Another thing is that the OnCurrenciesChanged does not get triggered at all.
I think (based on what I read so far) whenever the CustomMessageBox get called, the datacontext its operating at is no longer pointing to the MainPageViewModel thus it could not find the method. But I am not sure how to actually do this.
More details:
Exception happen after I click the left button (checkmark)
Updates
So far I have try the following:
<StackPanel Margin="12,0,0,0" DataContext="{Binding DataContext, RelativeSource={RelativeSource TemplatedParent}}"> //also tried with Self
and I also added this when I instantiate messageBox
var messageBox = new CustomMessageBox()
{
ContentTemplate = (DataTemplate)view.Resources["PivotContentTemplate"],
DataContext = view.DataContext, // added this
LeftButtonContent = "filter",
RightButtonContent = "cancel",
IsFullScreen = true
};
The idea is that when the messsagebox is created, the datacontext will be the same as when the view is instantiated. However, it seems that the datacontext does not get inherited by the PickerList
Ok so I managed to get this to work. The solution is not pretty and I think it beats the purpose of MVVM at the first place.
Based on http://wp.qmatteoq.com/first-steps-in-caliburn-micro-with-windows-phone-8-how-to-manage-different-datacontext/ , inside a template the DataContext will be different. So, I need to somehow tell ListPicker to use the correct DataContext.
The solution provided by link above doesn't work for me. I think it is because when ListPicker is called inside CustomMessageBox, MainPageViewModel is no longer available or it seems not to be able to find it as suggested by the exception. So as per above code example in the question, even if I set the correct DataContext to the CustomMessageBox, it does not get inherited somehow by the ListPicker.
Here is my solution:
var messageBox = new CustomMessageBox()
{
Name = "FilterCustomMessageBox", // added this
ContentTemplate = (DataTemplate)view.Resources["PivotContentTemplate"],
DataContext = view.DataContext,
LeftButtonContent = "filter",
RightButtonContent = "cancel",
IsFullScreen = true
};
In the XAML, I edited to this
<toolkit:ListPicker Header="currencies" SelectionMode="Multiple"
micro:Action.TargetWithoutContext="{Binding ElementName=FilterCustomMessageBox, Path=DataContext}"
micro:Message.Attach="[Event SelectionChanged] = [Action OnCurrenciesChanged($eventArgs)]">
It's ugly because both ViewModel and View need to explicitly know the Name. In WPF, you can just do something like this in the binding to inherit the DataContext of the parent/etc but this is not available for WP.
{Binding DataContext, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGrid}}}
If anyone has better workaround, do let me know!