This doesn't actually describe what I mean, but I'll try to explain. I've been using C# for an year now and never touched WPF. Only recently I've realized how awesome it is and started using it. I'm now facing a problem.
I want to let the user know the password/username are incorrect, so instead of the old WinForms MessageBox I want to make it more pleasent. I thought about creating a grid that tints the application darker, and then I'll be able to show some text on it. However - how's that possible?... Do you have any nicer ideas to show a message for the application (not a popup)? Thanks.
You can create an UserControl with translucent background (like #33000000), and 3-row grid to show title, message and OK button, like bellow:
<UserControl x:Class="ApplicationNameSpace.MessageControl" ... >
<Grid Background="#33000000" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Grid HorizontalAlignment="Center" VerticalAlignment="Center" Background="#FFFFFF" MinHeight="100" MinWidth="200">
<Grid.RowDefinitions>
<RowDefinition Height="30"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
<RowDefinition Height="35"></RowDefinition>
</Grid.RowDefinitions>
<Grid Grid.Row="0" Background="#EEEEEE">
<Label Content="Unable to Login" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
<Grid Grid.Row="1" Margin="10,20">
<TextBlock Text="Wrong username or password. Try again." HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
</Grid>
<Grid Grid.Row="2" Background="#EEEEEE">
<Button Content="OK" Width="80" Height="25" />
</Grid>
</Grid>
</Grid>
</UserControl>
To use, you can add the control at the end of your window, and change the visibility to Visible when needs to show it.
<Window x:Class="ApplicationNameSpace.MainWindow"
xmlns:local="clr-namespace:ApplicationNameSpace" ... >
<Grid>
...
<local:MessageControl Name="messageControl" Visibility="Collapsed" />
</Grid>
</Window>
You can also create a generic control that you pass to a show method the title and message content, like MessageBox show method. You can also add the user control element programmatically in the window in this method.
You can use the validation and the INotifyDataError which is on WPF 4.5 and you can show a nice message next to the textbox check this link for example
Related
I try to find a way to put my Combobox (UserControl) over another grid, but I can't. I'm tried to use Panel.ZIndex, ClipToBonus but they not working.
My XAML Code
<Grid>
<Grid.RowDefinitions>
<RowDefiniton Height="50"/>
<RowDefiniton/>
</Grid.RowDefinitons>
<Grid Background="#1e1e1e" ClipToBonus="false" Panel.ZIndex="10">
<control:Combobox x:Name="CbType" Width="200" Height="30" Panel.ZIndex="10"/>
</Grid>
<Grid Grid.Row="1" Background="#1e1e1e" ClipToBonus="false" Panel.ZIndex="1">
<control:ViewData x:Name="ViewControl" Width="500" Height="300" Panel.ZIndex="1"/>
</Grid>
</Grid>
I want when Combobox(CbType) drop-down it shows over ViewData(ViewControl). What way I can do for my problem?
Thank for your attention.
I am currently working on Windows Universal Apps.In that there is requirement to show menu from left side when User clicks on menu icon. I want add a ListView inside it and handle the selectionchanged event based on user's selected item. Now, the problem with Flyout is that it opens like a popup on clicking the icon but what I actually want to do is it should come from left side of the window .For e.g in Gmail application of android. Please can anyone suggest how to achieve this. Please find below my code which I added in Flyout below:
<Image Source="ms-appx:///Images/menu_image.png"
HorizontalAlignment="Left"
Tapped="Image_Tapped"
Width="60"
Height="90"
Grid.Column="0"
VerticalAlignment="Center">
<FlyoutBase.AttachedFlyout>
<Flyout>
<Grid x:Name="SettingsPane"
Background="{StaticResource AppBackGroundColor}"
Grid.Row="0"
Width="380">
<Grid.ChildrenTransitions>
<TransitionCollection>
<EdgeUIThemeTransition/>
</TransitionCollection>
</Grid.ChildrenTransitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0"
Margin="8">
<TextBlock Name="SidebarTitletxtblk"
FontSize="25"
TextWrapping="Wrap"
Style="{StaticResource BaseTextBlockStyle}" />
</StackPanel>
<ListView Grid.Row="1"
x:Name="LocationPickerList"
SelectionChanged="LocationPickTypeSelected"
Margin="0,10,0,0"
ItemContainerStyle="{StaticResource GenericListViewContainerStyle}"
ItemTemplate="{StaticResource LocationPickerListItemTemplate}"></ListView>
</Grid>
</Flyout>
</FlyoutBase.AttachedFlyout>
</Image>
You can't override the Flyout's standard transition. If you want to apply something else then you can use a Popup instead and customize it however you'd like. To have it slide in from the left apply an EdgeUIThemeTransition (if it's short) or a PaneThemeTransition (if it's full height) with Edge=Left.
For example:
<Popup x:Name="flyoutPane" IsOpen="False" IsLightDismissEnabled="True"
Width="320" HorizontalAlignment="Left">
<Popup.ChildTransitions>
<TransitionCollection>
<!--<EdgeUIThemeTransition Edge="Left" />-->
<PaneThemeTransition Edge="Left" />
</TransitionCollection>
</Popup.ChildTransitions>
<Grid Width="380" Height="{Binding ElementName=flyoutPane, Path=Height}" Background="{ThemeResource FlyoutBackgroundThemeBrush}" >
<TextBlock Text="Grid contents here" />
</Grid>
</Popup>
And trigger it from your Button Click (your Image sounds like it should be a Button rather than using Tap, unless you have an alternate keyboard method - you can template off the button look while keeping the button semantics).
private void Button_Click(object sender, RoutedEventArgs e)
{
// Height is only important if we want the Popup sized to the screen
flyoutPane.Height = Window.Current.Bounds.Height;
flyoutPane.IsOpen = true;
}
If you're doing many of these you can create a custom control with an attached property similar to FlyoutBase.AttachedFlyout.
I have a usercontrol that contains 2 rows. 1st row has a label and 2nd row has a scrollviewer with a canvas:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition />
</Grid.RowDefinitions>
<Label Grid.Row="0" Content="TITLE" HorizontalAlignment="Stretch" HorizontalContentAlignment="Center" Name="label1" VerticalAlignment="Top" FontSize="26" />
<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled">
<Canvas Background="White" />
</ScrollViewer>
</Grid>
In my main window.xaml I'm trying to add this user control and then add items to it's canvas.
<local:UserCanvas>
<label Content="Test" />
</local:UserCancas>
There problem here is that when I had that label in there it just overrides the "TITLE" label in row 1 of the user control. How do I add things so that they are placed on the cavas of the UserControl?
Instead of defining the Content in your UserControl, define the UserControl.ContentTemplate
For example, instead of writing
<UserControl ...>
<Grid>
...
<Canvas />
...
</Grid>
</UserControl>
use
<UserControl ...>
<UserControl.ContentTemplate>
<DataTemplate>
<Grid>
...
<Canvas>
<ContentPresenter Content="{TemplateBinding Content}"/>
</Canvas>
...
</Grid>
</DataTemplate>
</UserControl.ContentTemplate>
</UserControl>
If you use the first syntax, then specifying the Content when you use your UserControl will result in the existing Content getting overwritten, so your rendered Visual Tree ends up looking like this:
<local:UserCanvas>
<label Content="Test" />
</local:UserCancas>
By using the 2nd syntax, you're wrapping the Content in your ContentTemplate, so the rendered Visual Tree ends up looking like this:
<local:UserCanvas>
<Grid>
...
<Canvas>
<label Content="Test" />
</Canvas>
...
</Grid>
</local:UserCanvas>
I would try adding a public property (that you check and respond to in the user control's Page_Load()) and/or public method (that you just call from outside the control) to the user control which you can then access from your main program. Which way to go depends a bit on how complicated the actions you're needing to take will be. It looks to me like this will be simple enough to handle through the public property + Page_Load() method.
This is a problem I've been trying to solve for a couple of days but I'm yet to find a good solution.
I have a main WPF window which contains a StackPanel. I also have a class called "MessageManagement" which contains a List of custom WPF controls called "MessagePreview".
MessagePreview
<UserControl x:Class="FinalYearProject.MessagePreview"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="58" d:DesignWidth="254" Background="White" BorderThickness="1" BorderBrush="#FF320000">
<Grid Name="grid1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50" MaxWidth="50" MinWidth="50" />
<ColumnDefinition Width="197*" MinWidth="20" />
</Grid.ColumnDefinitions>
<Grid Grid.Column="1" Name="grid2">
<Grid.RowDefinitions>
<RowDefinition Height="31*" />
<RowDefinition Height="34*" />
<RowDefinition Height="33*" />
</Grid.RowDefinitions>
<Label Content="-ERROR-" Height="28" HorizontalAlignment="Left" Margin="2,1,0,0" Name="senderLabel" VerticalAlignment="Top" Foreground="#FF0000B4" Grid.RowSpan="2" />
<Label Content="-ERROR-" Height="33" HorizontalAlignment="Left" Name="previewLabel" VerticalAlignment="Top" Margin="-1,17,0,0" Grid.RowSpan="3" />
<Label Content="-Error-" Grid.Row="1" Height="28" HorizontalAlignment="Left" Margin="0,16,6,0" Name="timeLabel" VerticalAlignment="Top" Grid.RowSpan="2" Width="196" />
</Grid>
<Grid Name="grid3">
<Grid.RowDefinitions>
<RowDefinition Height="29*" />
<RowDefinition Height="27*" />
</Grid.RowDefinitions>
<Image Height="38" HorizontalAlignment="Center" Margin="3,0,6,20" Name="image1" Stretch="Fill" VerticalAlignment="Bottom" Width="41" Source="/FinalYearProject;component/Images/twitter-bird-light-bgs.png" Grid.RowSpan="2" />
<CheckBox Height="16" Margin="15,0,22,6" Name="checkBox" VerticalAlignment="Bottom" Grid.Row="1" IsChecked="False" />
</Grid>
</Grid>
MessageManagement
List<MessagePreview> unread = new List<MessagePreview>();
public bool messagesLocked()
{
foreach (MessagePreview m in unread)
{
if ((bool)m.checkBox.IsChecked)
return true;
}
return false;
}
MainWindow C#
MessageManagement messageManagement;
MessagesPanel1 is a blank StackPanel inside MainWindow
if (!messageManagement.messagesLocked())
{
foreach (Message m in messageManagement.getListOfMessages()
{
MessagesPanel1.Children.Add(m)
}
}
When you add the custom control to the StackPanel it creates a duplicate of the original, which means changing a value on the controls in the StackPanel does not affect the controls in my MessageManagement List.
Is there a way that I can reference my original controls so that they change together? I looked into DataBinding but I'm not sure if that's the right area.
Again, You do not make a List of UI elements in WPF. You use an ItemsControl and set its ItemTemplate Property to whatever UI you need to represent your items:
<ItemsControl ItemsSource="{Binding Messages}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<!-- Everything you placed in your usercontrol, or else an instance of your usercontrol itself -->
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
If saying "change" you mead a data, inside WPF you never and ever need to access UI elements directly, as they are subject to change. What you have to do is to read the data bound to them. With correct databinding setupped on that controls you will have always updated information.
Accessing UI elements is never easy, but except that, it's completely unreliable way to access your data, as the way control is injected into the VisualTree may be changed, so your code will fail on next update.
For example on how to architect that can have a look here:
WPF Data Binding Examples
User control details:
Have created drop down list control (Like as combo box), clicking on down arrow button, it displays a list below the text box
I have set zIndex property of my User control
Issue:
Case 1: When there is another user control (other than my custom user control), and if drop down list is displayed, other user control hides behind my user control. This is perfectly Ok
Case 2: There are 2 Custom User controls, if list is displayed from first user control, second user control appears on the list. This is where i am facing issue
XAML of my control is as below
<UserControlx:Class="UserControls.AutoCompleteComboBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Panel.ZIndex="1110" LostFocus="UserControl_LostFocus" Height="Auto">
<Canvas Name="MainCanvas">
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" MinWidth="150"></ColumnDefinition>
<ColumnDefinition Width="20"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBox Name="autoTextBox" Height="20" MinWidth="150" Width="Auto" MinHeight="20" Style="{DynamicResource AutoCompleteBox}" BorderThickness="2"
Margin="0,0,0,0" TextWrapping="NoWrap" Grid.Row="0" Grid.Column="0" HorizontalAlignment="Stretch" VerticalAlignment="Top"/>
<Button Content="6" FontFamily="Marlett" Grid.Row="0" Grid.Column="1" FontSize="15" Margin="0,0,0,0" Height="20" Width="20" HorizontalAlignment="Right" VerticalAlignment="Top" Background="{StaticResource BackgroudBlueBrush}" Click="Button_Click" Padding="0" Cursor="Hand"></Button>
<StackPanel Grid.Row="1" Grid.ColumnSpan="2" >
<ListBox Name="suggestionListBox" SelectionChanged="suggestionListBox_SelectionChanged" MouseDown="suggestionListBox_MouseDown"
Background="LightYellow" SnapsToDevicePixels="True"
Visibility="Collapsed"
MinWidth="150" IsHitTestVisible="True" MinHeight="70" Height="70"
VerticalAlignment="Top" LostFocus="suggestionListBox_LostFocus"/>
</StackPanel>
</Grid>
</Canvas>
</UserControl>
Your approach is not the right one to correctly manage the overlap of controls. Perhaps you may create some trick using the ZIndex property, but that won't be the solution.
If you need a drop-down control, the best way is to use a Popup control and play around it. Basically, it creates another borderless window, being child of the yours.
Another approach, maybe simpler but not good as the Popup, is using an Adorner. Maybe this one is the most similar techinique to the yours.
Cheers
Have you tried setting the ZIndex of the StackPanel to 1+ the control's zindex? That should raise the drop down portion above any other instance of your user control.
Canvas.ZIndex can be used on StackPanels.