Overlapping Transparent Views in a Prism Region - c#

I was wondering if there is a way to show two overlapping transparent views in one named Region? My example below shows two overlapped transparent views in their own separate named region container in the first grid row. In the second grid row we have one named region "RegionC". The first registered view is the one that is displayed ("ViewA"). Am I correct that if we have multiple views registered to a region then we can only show one view at a time? Is there a way to show two overlapped views in one named Region? Or is it standard practice to add another content control to support multiple views shown? One reason why I want to do this is so I can better separate my XAML code in separate views and inject them into one region container as needed.
ShellWindow.xaml
<Window x:Class="PrismDemo.Views.ShellWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:prism="http://prismlibrary.com/"
prism:ViewModelLocator.AutoWireViewModel="True"
Title="{Binding Title}" Height="150" Width="325" >
<Grid ShowGridLines="True">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ContentControl Grid.Row="0" prism:RegionManager.RegionName="RegionA" />
<ContentControl Grid.Row="0" prism:RegionManager.RegionName="RegionB" />
<ContentControl Grid.Row="1" prism:RegionManager.RegionName="RegionC" />
</Grid>
ShellWindow.xaml.cs
using Prism.Regions;
using System.Windows;
namespace PrismDemo.Views
{
public partial class ShellWindow : Window
{
public ShellWindow(IRegionManager regionManager)
{
InitializeComponent();
regionManager.RegisterViewWithRegion("RegionA", typeof(ViewA));
regionManager.RegisterViewWithRegion("RegionB", typeof(ViewB));
regionManager.RegisterViewWithRegion("RegionC", typeof(ViewA));
regionManager.RegisterViewWithRegion("RegionC", typeof(ViewB));
}
}
}
ViewA.xaml
<UserControl x:Class="PrismDemo.Views.ViewA"
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:local="clr-namespace:PrismDemo.Views"
mc:Ignorable="d"
d:DesignHeight="200" d:DesignWidth="300">
<TextBlock Text="ViewA" FontSize="20" />
ViewB.xaml
<UserControl x:Class="PrismDemo.Views.ViewB"
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:local="clr-namespace:PrismDemo.Views"
mc:Ignorable="d"
d:DesignHeight="200" d:DesignWidth="300">
<TextBlock Text="ViewB" FontSize="30" />

You should use ItemsControl instead of ContentConrol for your region RegionC and set its ItemsPanel to Grid.
Here is the XAML:
<ItemsControl Grid.Row="1" prism:RegionManager.RegionName="RegionC">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid IsItemsHost="True" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>

Am I correct that if we have multiple views registered to a region then we can only show one view at a time?
For regions in a ContentControl, yes, you are correct, because it can only have one Content at a time. But basically any control can host a region (provided you create an associated regionAdapter), for example, an ItemsControl or a TabControl can have multiple views inside them at the same time.
Is there a way to show two overlapped views in one named Region?
Yes, if you provide a RegionAdapter for a Grid, for example.
Or is it standard practice to add another content control to support multiple views shown?
Yes and no. Standard for multiple views in multiple regions, not standard for multiple views in the same region.

Related

Make region fullscreen in PRISM application by stretching user control

I am creating application using PRISM library. Currently i had only one region. Inside this region i put a user control with my view (as you can see below). Is just a some menu with property grid and a list to display data.
My user control:
By default my main window is full screen. When I run my application there are some remaking blank space below my user control.
Question:
How i can stretch my user control to fill all available space? As on picture below
What i've done:
- My user control container currently is DockPanel i tried put it to grid and other controls
- Delete user control sizes (width and height)
- Use viewbox inside shell.xaml (it destroys everything)
- Put user control to different cotainers inside shell.xaml
Currently shell.xaml is my "main window" I has only window tags with my user control.
I find similar questions on stack overflow but nothing helped me.
--- UPDATE ---
This is example of my user control code:
<UserControl x:Class="NewPrj.View.FullScreenTest"
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:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
mc:Ignorable="d">
<DockPanel Background="Blue" LastChildFill="True" VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<Menu DockPanel.Dock="Top">
<MenuItem Header="_New"/>
<MenuItem Header="_Something"/>
</Menu>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="350" />
</Grid.ColumnDefinitions>
<xctk:PropertyGrid Grid.Column = "1"
>
</xctk:PropertyGrid>
</Grid>
</DockPanel>
This is my shell.xaml window
<Window x:Class="NewPrj.Shell"
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:NewPrj"
xmlns:prism="http://www.codeplex.com/prism"
mc:Ignorable="d"
WindowState="Maximized"
Title="New Prj" MinHeight="600" MinWidth="800">
<Grid>
<ItemsControl Name="MainRegion" prism:RegionManager.RegionName="MainRegion" />
</Grid>
And this is actual result:
As I said before, there are many related topics but it does not work.
Reason:
This was not fully stretched because i use ItemsControl which use stack panel as default data template
Solution:
Change data template of ItemsControl or use User Control instead
<UserControl Name="MainRegion" prism:RegionManager.RegionName="MainRegion"/>
I found answer here

Why DataBinding is not propagating to UserControl

This morning I asked a question here and doing a simple working sample gave me a different behavior than expected.
Full working sample at GitHub. Main partial code below.
In this present case, the command is never propagated to any UserControl, either if the UserControl is use directly as a child of the Window. It also not work if the UserControl is used as a DataTemplate for a ListBox ItemTemplate.
I also include a hack button to fix the problem where the Command reach the UserControls. The hack come from StackOverflow.
But using the hack does not explain why UserControl does not receive the Command (without it) and using this hack also break the first rule of good coding: "Hi cohesion and Low coupling". The hack should be used in the the window code in order for it to manage the Command in the UserControl, my thought is that it should happen by default.
Why the command is not propagating by default to the UserControl and what should I do to propagate the command to the UserControl in a clean way?
Note: Using only one CommandBinding (removing one or the other) in the UserControl does not fix the problem .
Partial code:
<Window x:Class="CommandRoutingIntoItemTemplate.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:CommandRoutingIntoItemTemplate"
xmlns:system="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<local:UserControlTest></local:UserControlTest>
<ListBox Grid.Row="1">
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Aqua" BorderThickness="2">
<local:UserControlTest></local:UserControlTest>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.Items>
<system:String>1</system:String>
<system:String>2</system:String>
</ListBox.Items>
</ListBox>
<StackPanel Grid.Row="2" Orientation="Horizontal">
<Button Command="local:Commands.CommandTest">Put focus on TestBlock and click here to see if command occurs</Button>
<Button Click="AddHack">Hack</Button>
</StackPanel>
</Grid>
</Window>
UserControl:
<UserControl x:Class="CommandRoutingIntoItemTemplate.UserControlTest"
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:local="clr-namespace:CommandRoutingIntoItemTemplate"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.CommandBindings>
<CommandBinding Command="local:Commands.CommandTest" CanExecute="CommandTestCanExecuteUserControl" Executed="CommandTestExecuteUserControl"></CommandBinding>
</UserControl.CommandBindings>
<Grid>
<TextBox Text="UserControlTest">
<TextBox.CommandBindings>
<CommandBinding Command="local:Commands.CommandTest" CanExecute="CommandTestCanExecuteTextBox" Executed="CommandTestExecuteTextBox"></CommandBinding>
</TextBox.CommandBindings>
</TextBox>
</Grid>
</UserControl>
The reason that you are not getting commands invoked on your user control is that your buttons are not in separate focus scope. For WPF to pick up focused element for command target correctly, it needs to be in separate focus scope from command invoking control.
Framework will just traverse up visual tree from button looking for command bindings in their focus scope (in your case it won't find any). When framework does not find any command bindings in current focus scope, only then it looks into parent focus scope for focused element (In your case, buttons are in Window focus scope which has no parent scope so the search will end there).
Simply setting FocusManager.IsFocusScope="True" on your StackPanel will fix the issue.
You could also specify CommandTarget property on your buttons to point to your user control and not rely on focus.

Syncfusion GridDataControl nested in a TabControl: Column auto-resizing broken after switching tabs

I am rather new to WPF. On .NET 3.5 using C# I want to build a WPF application including Syncfusion's GridDataControl in a TabItem. The GridDataControl is supposed to auto-resize by specifying the column width in multiples of '*'. This works fine after the first start of the app. But after switching tabs and again switching back resizing is broken and the grid control remains fixed in size. Here is my xaml code:
<Window x:Class="SyncfusionGridData.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:SyncfusionGridData"
xmlns:syncfusion="http://schemas.syncfusion.com/wpf"
mc:Ignorable="d"
Title="MainWindow" Height="500" Width="525" DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid>
<TabControl>
<TabItem Header="Tab1">
<Grid Name="layoutRoot">
<syncfusion:GridDataControl x:Name="dataGrid"
AutoPopulateColumns="False"
ShowAddNewRow="False"
ItemsSource="{Binding GDCSource}">
<syncfusion:GridDataControl.VisibleColumns>
<syncfusion:GridDataVisibleColumn Width="*"
HeaderText="ContactName"
MappingName="ContactName">
</syncfusion:GridDataVisibleColumn>
<syncfusion:GridDataVisibleColumn Width="*"
HeaderText="ContactTitle"
MappingName="ContactTitle">
</syncfusion:GridDataVisibleColumn>
</syncfusion:GridDataControl.VisibleColumns>
</syncfusion:GridDataControl>
</Grid>
</TabItem>
<TabItem Header="Tab2">
<Label Content="2" />
</TabItem>
</TabControl>
</Grid>
where 'GDCSource' is an ObservableCollection of 'Person' and 'Person' has the properties 'ContactName' and 'ContactTitle'.
I tried using Syncfusion's own tab control (TabControlExt) but this shows the same behaviour. Not specifying the ItemsSource property and displaying only the header row shows proper resizing.
I do not really have an idea what this might be related to. Thanks for any help!
AutoSizing fails as soon as the GridDataControl is Unloaded.
Add the following property to your TabControlExt to prevent Unloading of the Tabs after they have been loaded.
IsDisableUnloadTabItemExtContent="True"

Changing BackGround color of combobox when ItemsSource is set

I have a wpf c# app.
I am using a combo box and I set the ItemsSource to my Observable collection.
what I would like is the background of the combo box not to be grey.
This control is housed in a UserControl.
<UserControl x:Class="InformedWorkerClient.UserControls.ucJobStatus"
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:local="clr-namespace:InformedWorkerClient.UserControls"
mc:Ignorable="d"
d:DesignHeight="27" d:DesignWidth="300" Background="White">
<Grid Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<ComboBox x:Name="cboJobStatus" Grid.Row="0" Grid.Column="0" Background="White"
DisplayMemberPath="Description"
SelectedValuePath="JobStatusRef"
SelectedValue="{Binding Path=JobStatus}" SelectionChanged="cboJobStatus_SelectionChanged" />
</Grid>
Additional:
This is what the background looks like after item is selected. I want the background to be white
You cannot do this due to a bug in the ControlTemplate for ComboBox.
Potential solution is to copy/edit the template and create your own.
This question is a duplicate. Perhaps the answer there can be updated with some more information. I searched for wpf cant change background of combobox and the top link is the MSDN answer on how to copy the template but even then the solution is riddled with issues with different Windows versions, aero theming, and does not address situations where users have high contrast turned on, and other accessibility issues.
I would recommend to use <ComboBox.ItemContainerStyle> and setup Background to Transparent for the container. Then each item background will be as in the ComboBox.

How to access this user control in Main Window

I have one user control in my WPF app
<UserControl x:Class="NewWPFApp.ProgressControl"
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="300" d:DesignWidth="300">
<Grid>
<Expander Header="{Binding Path=Headerval}">
<StackPanel Margin="10,4,0,0">
<DataGrid
x:Name="dataGrid"
AutoGenerateColumns="False"
ItemsSource="{Binding Path=records}"/>
</StackPanel>
</Expander>
</Grid>
and in my Mainwindow when I am doing this
<Window xmlns:NewWPFApp="clr-namespace:NewWPFApp" x:Class="NewWPFApp.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>
<ListBox x:Name="peopleListBox" >
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Background="AliceBlue">
<NewWPFApp:ProgressControl Height="100" Width="100"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
I cant see the output.
If I remove it from the Data template then it works.But not inside the data template.
What am I missing ???
Thanks
ListBox.ItemTemplate specifies how items added to a list box will be displayed. In your case, you uses your own custom control. However, at the same time you added no items to the list box so there is nothing to display. To populate the list box you can use binding e.g.:
<ListBox ItemsSource="{Binding ItemsToBeDisplayed}" x:Name="peopleListBox" >
...
</ListBox>
Where ItemsToBeDisplayed is a property of a view model (if you use MVVM pattern) that returns a collection of objects. If not you can populate ItemsSource without using binding:
var list = new List<People>();
//Add objects to a list
peopleListBox.ItemsSource = list;
I assumed that you have People class that models people you want to display in your application. People class should have Headerval and records properties because you use them in your your ProgressControl control. If you do as described, a new instance of your ProgressControl control will be created for every object in ItemsSource.

Categories

Resources