I am new to C# WPF, I have created a Popup window which contains a DataGrid to hold some data. In certain cases if there are any errors in the data I want to display this error in the same popup window at the bottom of the window (See screenshot). The idea is that the user can then click ok and the message will disappear displaying the full datagrid again.
Does anybody know how to do this?
I do not want another popup message box in a separate window, I want all messages to be displayed/stacked in the same pop window as the datagrid.
Below, there are 2 grids in the XAML: There is is the master grid, which contains the DataGrid, and another grid which contains the error UI. The error grid is normally collapsed (Visibility set to Visibility.Collapsed).
When the error message needs to be shown, the error grid's Visibility is set to Visibility.Visible, which shows the grid. When the user clicks on the "Dismiss" button, the error grid's Visibility is set to Visibility.Collapsed.
There is not a separate window or popup. Everything is contained within the master view.
XAML:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<DataGrid>
</DataGrid>
<Button Grid.Column="1" Content="Show Message Window" VerticalAlignment="Center" Click="Button_Click_1"/>
<!-- This is the "error grid"-->
<Grid VerticalAlignment="Bottom" Height="Auto"
Background="AliceBlue" Visibility="Collapsed" Name="grdError">
<TextBlock Text="Oops. This is an error!"/>
<Button Content="Dismiss" HorizontalAlignment="Right" Click="Button_Click_3"/>
</Grid>
</Grid>
Code Behind:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
grdError.Visibility = Visibility.Visible;
}
private void Button_Click_3(object sender, RoutedEventArgs e)
{
grdError.Visibility = Visibility.Collapsed;
}
}
Related
I want to manually control the behavior of InputPane to prevent it from showing or hiding automatically.
In my page that I put its image top, I want to InputPane show as user navigate to the page and keep showing until he/she clicks on specified button and prevent it from hiding if user clicks anywhere else in the page.
Also I want to InputPane remain hidden even if user clicks on TextBox.
I already know that there are TryShow() and TryHide(), but i can't revent auto showing and hiding.
The easy way to control it is by controlling focus of your TextBox. If you set IsTabStop on the TextBox to false - it won't take focus and so the SIP won't show up. If it already has focus - you'll need to move it out. If you want to display the SIP - focus the TextBox. Note that for performance reasons and also to prevent user confusion - it might make sense to use a TextBlock instead of a TextBox when the control should not be editable.
XAML
<Page
x:Class="App18.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App18"
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 />
<RowDefinition
Height="Auto" />
</Grid.RowDefinitions>
<TextBox
x:Name="myTextBox"
IsTabStop="False"
AcceptsReturn="True"
VerticalAlignment="Stretch"
TextChanged="MyTextBox_OnTextChanged"/>
<Button
x:Name="myButton"
Grid.Row="1"
Click="ButtonBase_OnClick">Edit</Button>
</Grid>
</Page>
C#
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
namespace App18
{
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
myTextBox.IsTabStop = true;
myTextBox.Focus(FocusState.Programmatic);
}
private void MyTextBox_OnTextChanged(object sender, TextChangedEventArgs e)
{
if (myTextBox.Text.ToLower().Contains("done"))
{
myTextBox.IsTabStop = false;
myButton.Focus(FocusState.Programmatic);
}
}
}
}
I have a WPF application using PRISM. The application is divided into two sections. The left pane is a menu pane and the right pane is a details pane. I have a toolbar also in the container pane which is a user control.
Now, I want that when I click the toolbar option I should be able to replace the right pane (details pane) with new user control/window. How can I do that? Currently, I have the following code in the toolbar edit button click which opens a new window I do not want a new window I want to replace the right pane window (details) window.
private void EditButtonClick(object sender, RoutedEventArgs e)
{
Window userEditWindow = new Window
{
Title = "User Edit",
Content = new UserEdit(),
Width = 600,
Height = 600
};
userEditWindow.Show();
}
Here is what the user interface looks like:
_______________________________________________________________________
PRISM shell container begins
________________________________________________________________________
| User control containing toolbar (edit, new, update, delete)
menu user control |____________________________________________________
|details pane user control
|
|
__________________________________________________________________ |_______________________________________________________________
PRISM shell container ends
_________________________________________________________________________
Above you can see the layout of my app! As you can see everything is inside the PRISM shell container. I am handling the events from user control toolbar in the code behind for the usercontrol toolbar as shown above. All I want is to replace the details pane when the toolbar is clicked. But I have no idea how to do that?
Look back at my answer to your previous question. You can then handle the Toolbar event by switching the DataEntryContext to a new instance of a different DataEntryViewModel and using a DataTemplate the UserControl in your Details Pane will change to reflect that.
In the MainView:
<Window
//usual window declarations>
<Window.Resources>
<DataTemplate DataType="{x:Type vm:FirstDetailViewModel}">
<view:FirstDetailView />
</DataTemplate>
<DataTemplate DataType="{x:Type vm:SecondDetailViewModel}">
<view:SecondDetailView />
</DataTemplate>
//more DataTemplates for other data entry views
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<view:ToolbarView Grid.Row="0"
DataContext="{Binding ToolbarContext}" />
<ContentPresenter Grid.Row="1"
Content="{Binding DataEntryContext}" />
</Grid>
</Window>
In the MainViewModel:
private void ToolbarContext_LoadFirstDetailExecuted(object sender, EventArgs e)
{
DataEntryContext = new FirstDetailViewModel();
}
private void ToolbarContext_LoadSecondDetailExecuted(object sender, EventArgs e)
{
DataEntryContext = new SecondDetailViewModel();
}
I am new for WPF so apologies if the answer is so obvious.
I got a WPF resizable window with a single stack panel control that is stretched vertically and horizontally to fill the window.
On window activated event, I use ".Children.Add" to add button controls to the panel. I have no idea how many buttons will be there at runtime so I checked "CanVerticallyScroll" in the panel. ScrollViewer.VerticalScrollBarVisibility is set to Visible by default.
I am still not seeing scroll bars at runtime though.
What properties did I miss to show scrolling panel with buttons?
Thanks
XAML:
<Window x:Class="ResMed.Ecp.Utility.ConnectionWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ConnectionWindow" Height="388" Width="641.6" Activated="Window_Activated">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="359*"/>
</Grid.RowDefinitions>
<StackPanel x:Name="pnlConnectionButtons" Margin="10,10.2,10.2,10" Grid.Row="1" CanVerticallyScroll="True"/>
</Grid>
</Window>
Code behind:
private void Window_Activated(object sender, EventArgs e)
{
for (int i = 0; i < 20; i++)
{
Button btn = new Button();
btn.Content = "Hello";
pnlConnectionButtons.Children.Add(btn);
}
}
Place your StackPanel inside a ScrollViewer:
<ScrollViewer>
<StackPanel>
<Button Content="Hello World"></Button>
...
...
</StackPanel>
</ScrollViewer>
You can also remove CanVerticallyScroll="True". From MSDN:
This property is not intended for use in your code. It is exposed publicly to fulfill an interface contract (IScrollInfo). Setting this property has no effect.
In my application loading popup is shown every time when I call It. But some times It just doesn't show and it is same situation. Popup is a custom UserControl object made with WPF.
Popup is in MainWindow.xaml:
<Viewbox Stretch="Fill">
<Grid>
<Grid x:Name="Body" Height="768" Width="1024" Background="{StaticResource SCBPassiveColor}" />
<src:InfoPane x:Name="InfoPaneMaster" Visibility="Collapsed" VerticalAlignment="Top" HorizontalAlignment="Center" />
</Grid>
</Viewbox>
In the Body of the main window application loads selected layout/view. Before new layout is loaded program calls :
LayoutCommands.DisplayInfoPane(msgLoginSuccess, ROPInfo.Info, null);
implementation:
public void DisplayInfoPane(string infoText, ROPInfo infoType, int? displayTime)
{
StopTimer();
SetTimer(displayTime ?? DefaultDisplayTime);
PrepareInfoPane(infoText, infoType);
colCloseIcon.Width = new GridLength(0);
this.Visibility = Visibility.Visible;
}
The popup automatically closes (sets visibility to collapsed) after default time.
Why sometimes this popup just doesn't show? Is this associated with rendering?
I am trying to implement a kind of single-line tab control in WPF which shows scroll buttons left and right of the area containing the tabs. The tabs are implemented inside a custom control. The scroll buttons shall be displayed only if the window is too small to display all tabs.
When the window is resized by dragging on its borders, everything works as expected.
But when the window is maximimized and then restored, then the right scroll button remains hidden.
The problem seems to appear only if the Visibility property of the right scroll button is data-bound to a dependency property of the custom control that is updated within the custom control's Measure pass.
My question is: am I using WPF correctly here, or is there something that needs to be done in a different way? (Please note: I need to use the data-binding and the custom control; therefore please avoid answers that suggest to take a completely different approach.)
Here is a small sample program which illustrates the problem:
When width is small:
When width is large:
These are the files of the sample program:
MainWindow.xaml:
<Window x:Class="GridTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:gridTest="clr-namespace:GridTest"
Title="MainWindow" Height="350" Width="525">
<Grid x:Name="theGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Button x:Name="btnScrollLeft" Content="<" Grid.Row="0" Grid.Column="0" Width="30"/>
<gridTest:MyCustomControl x:Name="cust" Grid.Row="0" Grid.Column="1"/>
<Button x:Name="btnScrollRight" Content=">" Grid.Row="0" Grid.Column="2" Width="30"
Visibility="{Binding ElementName=cust, Path=ShowButton}"/>
<TextBox Text="The content goes here..." Grid.Row="1" Grid.ColumnSpan="3"
Background="LightGreen" HorizontalContentAlignment="Center" VerticalContentAlignment="Center"/>
<Button x:Name="btnRedraw" Grid.Row="1" Grid.Column="1" Content="Redraw" VerticalAlignment="Bottom"
HorizontalAlignment="Center" Click="btnRedraw_Click" />
</Grid>
</Window>
MainWindow.xaml.cs:
using System.Windows;
namespace GridTest
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void btnRedraw_Click(object sender, RoutedEventArgs e)
{
theGrid.InvalidateMeasure();
}
}
}
MyCustomControl.cs:
using System;
using System.Windows;
using System.Windows.Controls;
namespace GridTest
{
public class MyCustomControl : Control
{
static MyCustomControl()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(MyCustomControl), new FrameworkPropertyMetadata(typeof(MyCustomControl)));
}
public Visibility ShowButton
{
get { return (Visibility)GetValue(ShowButtonProperty); }
set { SetValue(ShowButtonProperty, value); }
}
// Using a DependencyProperty as the backing store for ShowButton. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ShowButtonProperty =
DependencyProperty.Register("ShowButton", typeof(Visibility), typeof(MyCustomControl), new UIPropertyMetadata(Visibility.Visible));
protected override Size MeasureOverride(Size constraint)
{
if (constraint.Width > 800)
{
ShowButton = Visibility.Collapsed;
}
else
{
ShowButton = Visibility.Visible;
}
double width = Math.Min(2000.0, constraint.Width);
double height = Math.Min(50.0, constraint.Height);
return new Size(width, height);
}
}
}
Generic.xaml:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:GridTest">
<Style TargetType="{x:Type local:MyCustomControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:MyCustomControl}">
<Border Background="LightCyan">
<TextBlock VerticalAlignment="Center" TextAlignment="Center">Custom Control</TextBlock>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
The problem can be reproduced as follows:
Make sure that the window is small, such that the right scroll button is visible.
Now maximize the window. => The right scroll button should become invisible.
Now restore the window to its original size. => The right scroll button should become visible again. (The problem is: the right scroll button remains invisible.)
EDIT: Just for information: I could reproduce the problem with both VS2010+.NET4.0 and VS2013+.NET4.51.
You need to dispatch your ShowButton visibility change back into the dispatch queue for this to work(give the application the time it needs for the render and in sequence) rather than do it directly in the MeasureOverride method.
So say I change your MeasureOverride to
protected override Size MeasureOverride(Size constraint) {
if (constraint.Width > 800) {
Application.Current.Dispatcher.BeginInvoke(
new Action(() => ShowButton = Visibility.Collapsed));
} else {
Application.Current.Dispatcher.BeginInvoke(
new Action(() => ShowButton = Visibility.Visible));
}
double width = Math.Min(2000.0, constraint.Width);
double height = Math.Min(50.0, constraint.Height);
return new Size(width, height);
}
You can see it works fine.
With the original code you posted, you can see that even when you maximize your Window, the Button on the right will be hidden but not actually Collapsed like that your setting it to, that would be again due to the same reason of the control not getting it's new size.
Also after restoring and having the Button remain hidden, if you re-size the Window by dragging it's size, you can see the button become Visible again.
By dispatching the Visibility change, if you have a break-point in your MeasureOverride function, you can see it gets called twice(once for Window size change and second size change due to Button being Hidden/Shown) essentially when maximizing/restoring the Window and thereby produce the correct dimension calculations and your desired output.
Having worked with some custom Panels before, I seem to remember that the value passed into the MeasureOverride method is not the actual size used... try moving that code to the ArrangeOverride method instead and see what happens.