I'm learning WPF, so bear with me.
I would like to have my WPF application flash in the user's face if a certain event is fired.
What is the best way to "notify" the user? I really want the user to react!
Cheers, Patrick
Environment: Windows7/64bit/.Net4
If you want the user to react you can force them to by simply opening a modal dialogue. The most lightweight of which being the MessageBox. You can also create normal modal windows using their ShowDialog method, you can make those windows as "fancy" as you want by getting rid of their normal appearance. This is achieved by setting the WindowStyle to None and AllowsTransparency to true, this will remove all the frame elements, so the window is now pure content.
Popups are handy for non-modal notifications and they already are content-only, but setting their AllowsTransparency to true may also be desired if you want rounded corners for example.
Best is entirely subjective and depends on many context variables but here is how I do it MVVM style.
In your main view model, define a property
pubic ObservableCollection<AlertViewModel"> Alerts { get; private set; }
in my case the AlertViewModel has only a "Message" property and a "Dismiss" RelayCommand.
In the XAML of your main view add
<Grid>
<all of my other other view controls>
<ItemsControl x:Name="AlertsControl" Opacity="50" ItemsSource="{Binding Alerts}"/>
</Grid>
Make sure it is the last item in the main container of your main view. This ensures it has the highest z order and will appear on top of all other controls.
Here is the data template for this view model
<DataTemplate DataType="{x:Type vm:AlertViewModel}">
<Border CornerRadius="10" Margin="3" Background="Red">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="75"></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Button Margin="10" Grid.Column="0"
Command="{Binding ElementName=theWindow, Path=DataContext.DismissAlarmCommand}"
CommandParameter="{Binding}">Dismiss</Button>
<TextBlock Foreground="White" FontWeight="ExtraBold" Grid.Column="1"
Text="{Binding Message}" FontSize="20"
VerticalAlignment="Center" HorizontalAlignment="Left"></TextBlock>
</Grid>
</Border>
</DataTemplate>
Now,
Alerts.Add( new AlertViewModel() { Message = "Danger Will Robinson! Danger!" } );
Will pop a Bright red alert box onto the top of your main form. It does not go away until the user presses "Dismiss"
If you want it to flash or fade in and out or bounce up and down you can add animation in the data template.
You can use a Converter or data to Enable/Disable the rest of the controls in the app byt binding to AlertsControl.HasItems
Good luck.
Related
I'm trying to get a fresh little reactUI WPF app up and running. However ViewModelViewHost causes me problems. It does not fill the widow but stays at its minimum required measures. (as calculated off of its children)
I have this bit of XAML in my MainWindow.xaml:
<Grid Grid.Row="1" Name="WorkArea">
<reactiveUi:ViewModelViewHost ViewModel="{Binding .}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0" DataContext="{Binding DocVm}">
<reactiveUi:ViewModelViewHost.DefaultContent>
<Label Content="no file" FontStyle="Italic" FontSize="33" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</reactiveUi:ViewModelViewHost.DefaultContent>
</reactiveUi:ViewModelViewHost>
</Grid>
So there is a grid in the MainWindow and the middle part shall be occupied by the ViewModelViewHost hence applying Horizontal and VerticalAlignment. I also tired getting rid of the second grid, but no difference. What actually happens (as seen in Snoop) is: The ViewModelViewHost complies to the stretch setting but its templated part PART_CurrentContentPresentationSite does not comply. It stays at Left + Top. What should I do, how was this intended?
Replace the template...
BTW. It also seems not to be enough just to set the ViewModel-property in order to have the view binding at the view model. You also have to set the DataContext.
You need to use the HorizontalContentAlignment and VerticalContentAlignment and set those to stretch.
I would like to know if there's a way to implement a responsive Master/Detail page using only one. What I want is something exactly like the Project here:
https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/XamlMasterDetail
Except for the detail that instead of using two pages and navigating from one to another I would only use one page.
Is there a way to do it? If so, could you link me a working example?
Except for the detail that instead of using two pages and navigating from one to another I would only use one page.
After going through the project, I found it implemented a responsive master/detail experience based on the size of the screen. When the app view is sufficiently wide, the master list and detail view should appear side by side in the same app page. However, on smaller screen sizes, the two pieces of UI should appear on different pages, allowing the user to navigate between them. From my point of view, I think this is a good solution for implementing a responsive master/detail experience.
Is there a way to do it? If so, could you link me a working example?
The project already shows how to implement responsive Master/Detail in UWP using only one page, but it implements more and that makes it a little complex to understand. So I make a simple example which directly shows how to implement responsive Master/Detail in UWP using only one page.
Following is the main steps:
First, create a ListView to show master information in xaml page:
<!--Master VIEW-->
<ListView x:Name="ItemListView" Margin="0,0,0,8">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel HorizontalAlignment="Left" Margin="10,8,0,0">
<TextBlock Text="{Binding Title}" FontSize="25" Width="400" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Second, specify the details view that shows the details item related to the selection on the master list in the same xaml page:
<!--DETAILS VIEW-->
<StackPanel Grid.Column="1" x:Name="ContentPanelDetail" Margin="10,0,0,0" DataContext="{Binding SelectedItem, ElementName=ItemListView}">
<TextBlock Text="{Binding Title}" MaxHeight="80" FontSize="30" HorizontalAlignment="Left" Margin="0" />
<TextBlock x:Name="DetailTextBlock" FontSize="35" Text="{Binding Content}" HorizontalAlignment="Left" Margin="0,18,40,0" Width="500" Height="Auto" TextWrapping="Wrap" />
</StackPanel>
Then, set the ItemsSource for the ListView in code behind:
public MainPage()
{
this.InitializeComponent();
//set the ItemsSource for the ListView
ItemDetails messageData = new ItemDetails();
ItemListView.ItemsSource = messageData.Collection;
ItemListView.SelectedIndex = 0;
}
Last but not least, put Master View and Details View into a SplitView and use VisualStateManager to make it more responsive.
Here is the simple example and the output for your reference.
To implement Master/Detail pattern on your page, you don't have to do it yourself. Instead you can use MasterDetailsView control from UWP Community Toolkit, it does a lot work for you + it is well documented.
Note: For details section of the control, do not set background to null (NoSelectionContent will be visible).
Could anyone explain how to use the XAML popups with Caliburn Micro.
Thanks
Edit:(Made my code more releavent to what I want to achieve)
When I define a popup in xaml like this:
<Button x:Name="ShowPopup" Content="Popup"/>
<Popup x:Name="my_popup_xaml" Grid.Row="2">
<Border BorderThickness="2" Margin="10" BorderBrush="Green">
<StackPanel Background="LightBlue">
<TextBlock Text="Select Option" FontSize="21" Margin="10,0" />
<StackPanel Orientation="Horizontal" Margin="0,10">
<Button x:Name="SelectPhoto" Content="Select photo From Library" Width="215"/>
<Button x:Name="CapturePhoto" Content="Use Camera" Width="215"/>
</StackPanel>
</StackPanel>
</Border>
</Popup>
How do I display this popup using the WindowManager?
Should I create new View Model for this because I just need to use PhotoChooser task and the Camera Capture task here?
How do I bind Popup to my View Model.
Edit:
#Charleh, Your Suggestion for using with windowmanager with a separate ViewModel worked, with a minor tweak.
I removed the <Popup> tag and used the window manager to display the popup.
But now I cannot close the popup and the popup is cropped as it's displayed at the top of the screen. How do I fix this?
Edit: I was able to close the dialog using the the Screen's TryClose() Method.
When I used the ShowDialog method instead the of the ShowPopupmethod and the alignment of the window was a bit better but it is still stuck at the top and wont align in the center.
Edit: I have created a new PhoneApplicationPage(Windows Phone 8 equivalent of window) and displayed it as a dialog. The problem with this approach is that the PhoneApplicationPage is not stretching automatically to fill the screen space(Which it does when not displayed as a dialog). It's just stretching to accommodate the content inside it. Setting `VerticalAlignment="Stretch" has no effect.
Giving the Height property a particular value is not suitable because of it does not adjust to well to different phone resolutions.
#Charleh I tried specifying height and width like this:
Dictionary<string, object> properies = new Dictionary<string, object>();
properies.Add("Height", 768);
properies.Add("Width", 480);
windowManager.ShowDialog(new ImageSelectorPopupViewModel(),null,properies);
This Code has no effect (although specifying the height in Xaml works but I cannot use that as I have to accommodate for different screen resolutions on the phone)
You really need to read up on Caliburn Micro before you post - there are literally tons of articles showing how to bind commands on your view to methods on your VM
To do so in this case either:
Bind using convention by giving your button the same name as the method
<Button x:Name="ShowPopup" />
Bind using action message syntax:
<Button cal:Message.Attach="[ShowPopup]" />
All the answers are here: http://caliburnmicro.codeplex.com/documentation
(specifically: http://caliburnmicro.codeplex.com/wikipage?title=All%20About%20Actions&referringTitle=Documentation)
You do the same thing with your button, so you can do the same thing with your popup
(have you also considered using Caliburns WindowManager which has a ShowPopup method?)
Edit:
On re-reading it looks like you want to use the same ViewModel for your current View and Popup - is this the case or do you want a new ViewModel for your Popup? I'd suggest using WindowManager, and creating a ViewModel for the popup - it will be more in-line with what CM already does
I need to create a button with two lines of text:
The first one is Command Title like "Save"
The second one is a Description of the Command like "The application state will be saved"
So I have written the next xaml:
<Button Margin="0,128,0,0" Padding="10,5" HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch">
<StackPanel Margin="0" UseLayoutRounding="False">
<TextBlock FontSize="{StaticResource PhoneFontSizeMediumLarge}" FontFamily="{StaticResource PhoneFontFamilySemiBold}">Save</TextBlock>
<TextBlock Style="{StaticResource PhoneTextSubtleStyle}" Margin="0">The application state will be saved</TextBlock>
</StackPanel>
</Button>
This code working well except a one issue. The Description line becomes invisible when the button is pushed.
I'm sure the root cause is the low contrast color of the description line. But I don't know how to fix it.
Update: I have tried to use the PhoneTextSubtleStyle style but still have the same issue.
You could retemplate the Button (using the Control.Template property) to look different so that when pushed it no longer interferes with the content.
Could you try something like this
System.Windows.Visibility.Visible;
System.Windows.Visibility.Hidden;
or
System.Windows.Visibility.Collapsed
here is a link that will show an example of how to use this inside of a StackPanel
How to: Change the Visibility Property
I have a TabControl with TextBox controls in the ContentTemplate. When I type some text in one tab and switch to another tab, the Undo history in the original tab is gone when I go back.
Another problem that comes up is any text that was selected is deselected and the caret moves to the beginning of the TextBox.
If I make a window with just hardcoded TabItem controls, the undo history is preserved. The issue has something to do with my binding or templates.
Here is my XAML for the main window
<Window x:Class="TabbedTextAreaTest.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/>
</Grid.RowDefinitions>
<Button Command="{Binding AddNewTab}">Add Tab</Button>
<TabControl ItemsSource="{Binding Tabs}" Grid.Row="1">
<TabControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Header}"/>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate>
<TextBox Text="{Binding Content, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
</Grid>
</Window>
Is there a way to preserve the undo/redo history and selected text when switching tabs without manually catching those commands?
When you use a TabControl which gets its tabs via databinding on ItemsSource, WPF doesn't keep the visual tree for each item around as you switch. Thus, when you switch from tab 1 to tab 2, then back to tab 1, the controls on tab 1 are not actually the same control instances which you saw on tab 1 the first time.
There are a number of ways around to deal with this - TabControls which have explicit TabItem instances do keep their visual trees when you switch tabs, so probably the easiest way to do it is to wrap your collection of tab items in something which makes TabItems for them.
Unfortunately right now I can't find a link to an example of how to do this. There are references to articles elsewhere on SO, but they all seem to point to pages which no longer exist, and I don't have time to dig any deeper.
The reason is simple. If you think the both operation you complain about are strictly UI operations: Undo: user editing on the UI control, selection: selection of the text on UI control.
When you swicth Tab to another and go back, what happens in WPF is that all controls are rebinded to there data (ModelView normally, or just Model) again, as if you was showing them for the first time. So they loose their UI appearance attributes.
To manage that correctly in Tab environment in WPF you need to manage Undo/Redo stack by your own.
Good luck.