I have a RadBusyIndicator on my UserControl like so:
<Grid>
<!-- Other Content -->
<t:RadBusyIndicator IsBusy="{Binding IsBusy}"></t:RadBusyIndicator>
</Grid>
And whenever I click in the design view it goes to the BusyIndicator.
I can set the Panel.ZIndex to be negative to select the "Other Content", but this will cause the RadBusyIndicator to be behind the "Other Content"
I tried using a binding for the ZIndex like so:
<t:RadBusyIndicator Panel.ZIndex="{Binding BusyZIndex}" IsBusy="{Binding IsBusy}"></t:RadBusyIndicator>
But it doesn't help.
So the question is:
How do I have the RadBusyIndicator on "Top" of all the "Other Content" but still be able to click(in the designer) and go to the xaml line for that control?
The BusyIndicator needs to be "on top" to be in front of the controls. That makes it also on top in the designer.
There may be better ways of solving this, but what comes into mind is to make the BusyPanel a Resource on the UserControl, and then add it in the Grid control OnApplyTemplate or Loaded by code.
Here is the UserControl's XAML.
<UserControl x:Class="WpfApplication2.UserControl1"
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"
xmlns:t="REFERENCE.TO.THE.RAD.ASSEMBLY"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
<t:RadBusyIndicator x:Key="TheBusyIndicator" IsBusy="{Binding IsBusy}">
</UserControl.Resources>
<Grid x:Name="LayoutRoot">
<Button Content="Some content to the button"
Height="25"
Width="200"/>
</Grid>
</UserControl>
I have added the BusyIndicator as a Resource with the Key "TheBusyIndicator".
I have also added x:Name="LayoutRoot" to the Grid which will contain the BusyIndicator.
The Grid can of course have another name if it in fact is not the layout root control.
By adding the BusyIndicator to the Children collection last, it will appear in front of all other controls that are added by the markup code.
Here is the code
UserControl's Constructor:
public UserControl1()
{
this.Loaded += new RoutedEventHandler(UserControl1_Loaded);
}
The execting code:
private void UserControl1_Loaded(object sender, RoutedEventArgs e)
{
this.LayoutRoot.Children.Add(this.Resources["TheBusyIndicator"] as RadBusyIndicator);
}
I never use UserControls anymore, only CustomControls where the XAML goes to "Generic.xaml" and I have no editor to work in. So I have not seen this problem for a while.
Related
I created sample Wpf application and installed Extended WPF Toolkit (NuGet package). Here's my xaml code for showing BusyIndicator.
<Window x:Class="WpfApp3.Progress"
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:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
xmlns:local="clr-namespace:WpfApp3"
mc:Ignorable="d"
WindowStyle="None"
BorderThickness="0"
Title=""
VerticalAlignment="Center"
HorizontalAlignment="Center"
SizeToContent="WidthAndHeight"
d:DesignWidth="300"
d:DesignHeight="300">
<xctk:BusyIndicator IsBusy="True"
HorizontalAlignment="Center"
VerticalAlignment="Center"></xctk:BusyIndicator>
</Window>
Showing the progress window is triggered with this code:
private void Button_Click(object sender, RoutedEventArgs e)
{
Progress w = new Progress
{
Owner = Application.Current.MainWindow,
WindowStartupLocation = WindowStartupLocation.CenterOwner
};
w.Show();
}
My question is simple. How to show BusyIndicator in the middle of the MainWindow screen. As Shown from the picture below it's not centered as it should be. Note that I use SizeToContent="WidthAndHeight"
Having a seperate window to display the busy indicator and will result in unwanted behaviour. What happens if the original window is maximised, moved etc.?
Consider adding the busy indicator to the main screen. Usually I create an overlay region that is used to display message dialogs, progress bars etc..
<Window>
<Grid>
<Application stuff ....>
</Application stuff>
<ContentControl regions:RegionManager.RegionName="OverlayRegion"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch" />
</Grid>
</Window>
I'm using Prism here but you can replace the ContentControl with anything, such as the BusyIndicator and manipulate the visibility of the control.
Solved it by removing Window.SizeToContent property and by adding VerticalAlignment and HorizontalAlignment properties to BusyIndicator (actually now I used spinner, but this doesn't make any difference in solution).
<Window x:Class="Test.Progress"
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"
xmlns:extToolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit/extended"
WindowStyle="None"
AllowsTransparency="True"
BorderThickness="0"
Title=""
WindowStartupLocation="CenterOwner"
ShowInTaskbar="False"
Background="Transparent"
d:DesignWidth="200"
d:DesignHeight="200"
MaxWidth="250"
MaxHeight="250">
<xctk:BusyIndicator IsBusy="True"
HorizontalAlignment="Center"
VerticalAlignment="Center"></xctk:BusyIndicator>
</Window>
The problem is because BusyIndicator was not designed to use it in separate window
The BusyIndicator is a ContentControl. What this means is that the BusyIndicator can contain a single child element within it?s open and closing tags.
Additionally if you do, first thing that is shown is small ui control (12x12 pixels) and after some latency finally the progress bar/busy indicator is shown.
By specifying SizeToContent='WidthAndHeight', xaml automatically resizes height and width relative to content. In this case (12x12) ui control is taken, and after some latency time finally as mentioned above busy indicator is shown. But by that time, the xaml ui renderer already applied SizeToContent and therefore you would have to manually re-position the progress bar.
I'm not really sure how xaml ui renderes works without specifying SizeToContent, but apparently it re-positions the busy indicator correctly after it is shown.
I'm building a WPF application and using caliburn.micro for MVVM.
I'm having dozens of views (UserControls).
The views has a header body and footer.
As shown in below image, header contains two buttons for crud operation, and the footer contains a status bar.
The header and footer parts will be same for all views, but the body contents will be different for view to view.
Currently I'm having repeated code for header and body for each view, and now I'm trying to eliminate repeating code.
To achieve this I'm thinking to make a common base view, to share with all other views.
Current Implementation
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel>
<Grid Name="Header/>"
<Grid Name="Body/>"
<Grid Name="Footer/>"
</StackPanel>
</UserControl>
Trying to acheive something like
Base View
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel>
<Grid Name="Header/>"
<!-- {Placeholder for child view} -->
<Grid Name="Footer/>"
</StackPanel>
</UserControl>
ChildView
<Grid Name="Body"/>
May be my approach is wrong (I'm bit new to WPF).
My goal is to eliminate the repeating code, by inheriting some controls into the view.
How can I combine base view with child view?
Could anyone advice me to achieve my requirement?
Providing some code example will be highly appreciated.
You could for example define the common header and the footer in the parent window, or in two separate user controls that you create in the XAML markup of the parent window, and then inject the child views into the same window using a ContentControl, e.g.:
<Window x:Class="WpfApplication1.MainWindow"
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:local="clr-namespace:WpfApplication1"
mc:Ignorable="d"
Title="MainWindow" Height="300" Width="300">
<StackPanel>
<local:HeaderUserControl />
<ContentControl Content="{Binding CurrentViewModel}">
<ContentControl.Resources>
<DataTemplate DataType="{x:Type local:ViewModelA}">
<local:ViewA />
</DataTemplate>
<DataTemplate DataType="{x:Type local:ViewModelB}">
<local:ViewB />
</DataTemplate>
</ContentControl.Resources>
</ContentControl>
<local:FooterUserControl />
</StackPanel>
</Window>
The child views doesn't know anything about the header and the footer.
You can nest your UserControls just like you can nest any other element so you could do something like this
<UserControl x:Name="HeaderControl">
<UserControl x:Name="ChildControl"/>
</UserControl>
Then you'd use a DependencyProperty in your header control to associate your child control with it something like this
public UserControl ChildControl
{
get { return (UserControl)GetValue(ChildControlProperty); }
set { SetValue(ChildControlProperty, value); }
}
public static readonly DependencyProperty ChildControlProperty =
DependencyProperty.Register("Text", typeof(UserControl), typeof(UserControl), new PropertyMetadata(null));
This article gives a nice overview - I know it says Silverlight but it uses the same basic approach.
I have a user control in my wpf application. and inside this user control i have web browser control.
when I navigate to some web page, it is not showing up anything. I can see that http call is happening and navigated event of web browser control is firing. but nothing is showing up.
Any help would be appreciated.
XAML looks like this
<UserControl
x:Class="Client.Module.LmpView"
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"
DataContextChanged="UserControl_DataContextChanged"
xmlns:module="clr-namespace:Client.Module"
xmlns:WinForms="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms">
<!--
<StackPanel>
<WindowsFormsHost x:Name="wfh" Width="400" Height="400"/>
</StackPanel>
-->
<TextBlock>
<WebBrowser Width="400" Height="400" Navigated="LinkedInProfileDisplayControl_Navigated" x:Name="LinkedInProfileDisplayControl" AllowDrop="True" />
</TextBlock>
</UserControl>
Code behind file
private void UserControl_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if (this.DataContext != null)
{
LinkedInProfileDisplayControl.Navigate((this.DataContext as LinkedInMemberProfileViewModel).LinkedInMemberProfileUrl);
}
}
try any of these:
1) make sure you have no AllowsTransparency="true" anywhere
2) see if LinkedInProfileDisplayControl.Navigate("http://google.com") works
3) make sure WebBrowser is actually showing, set its Visibility=Visible.
4) see if it works when you detach from navigated event.
5) Use snoop to inspect visual tree.
Lets say I have next layout:
Window
UserControl
UserControl
UserControl
Button
GridControl
GridCell
And lets say that GridCell currently has Keyboard focus. If a user clicks on button. a message is displayed to user to confirm action. No matter of what choice the user selected (Yes or No), a focus should return to a CurrentCell on GridControl. By default, after a user selected some option, a focus would return to Window (reported by Snoop). I would assume that a Button that was clicked would retain focus, but apparently not.
Handling of button Command is done in ViewModel (MVVM).
How do I return keyboard focus to a current cell in grid?
You can probably pretty safely work around this problem by setting FocusManager.IsFocusScope="true" on your button or if there are multiple buttons the parent element they are in (eg StackPanel or whatever).
There are a few potential issues with this if you are using RoutedCommands. Basically RoutedCommands don't always work the way you expect them to inside of focus scopes. It sounds like you are binding directly to a command on the View Model though so that shouldn't be a problem. If you would like to read more about the RoutedCommand issue check this code project article out.
Here is what my sample code to verify this works looks like for your reference.
XAML:
<Window x:Class="WpfApplication1.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 Margin="25">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<!--You could also have the FocusManager.IsFocusScope set on the Border instead-->
<Border Margin="0,0,0,15">
<Button FocusManager.IsFocusScope="True" Click="ButtonBase_OnClick">Click me!</Button>
</Border>
<TextBox Grid.Row="1" x:Name="MessageTextBox"></TextBox>
</Grid>
</Window>
C#:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
MessageBox.Show("Clicked, message: " + MessageTextBox.Text);
}
}
I have a UserControl that contains a listbox.
On the parent window, I have this UserControl and a button.
Ideally I'd like to use the ChangePropertyAction behavior on the parents button, and tie it to the UserControl's listbox count.
The idea being that if there are no entries in the listbox inside the usercontrol, the button on the parent window is hidden. The listbox is bound to an observablecollection.
Do I create a DependencyProperty to do this? I'm not sure how to bind the listbox's count to this property though.
Thanks so much for any insight into the right way to do this.
You can use a ElementName Binding to reach the ListBox state from the Button. You then want to use a BooleanToVisibilityConverter to do the magic.
Like so:
<Window x:Class="NestedTreeTest.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="200" Width="300">
<Window.Resources>
<BooleanToVisibilityConverter x:Key="boolToVisibilityConverter" />
</Window.Resources>
<StackPanel>
<Button Visibility="{Binding ElementName=myList, Path=HasItems, Converter={StaticResource boolToVisibilityConverter}}">
Text
</Button>
<ListBox x:Name="myList">
<!--<ListBoxItem>Item A</ListBoxItem>-->
</ListBox>
</StackPanel>
</Window>
comment out, or uncomment the ListBoxItems to see it working...
I ended up using the Messenger classes from the MVVM Futures project to let the UserControl's ViewModel signal other ViewModels of the change.
This let's multiple listeners monitor for the same changes, without the need for extra Dependency Properties.