WPF UserControl Not Displaying - c#

I deleted my previous question to rephrase appropriately, since my previous post was neither helpful nor complete, imo.
For clarity: I'm using the Prism framework and abiding by a strict MVVM pattern.
Problem: When I load a UserControl, defined in some module, ModuleA, it does not display in the Shell view. However, if I load my UserControl within an ItemsControl, the elements I have defined appear, but they are all 'squished together'.
In ModuleA, I have the following UserControl:
<UserControl ...
...>
...
<Grid>
... My Content Here ...
</Grid>
</UserControl>
Now, in my project, I have defined the Shell thusly:
<Window ...
...>
...
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="10"/>
<RowDefinition Height="10"/>
<RowDefinition Height="10"/>
</Grid.RowDefinitions>
<Border Grid.Row="0" .../>
<UserControl Grid.Row="1" prism:RegionManager.RegionName="ModuleARegion"/>
<Border Grid.Row="2" .../>
</Grid>
</Window>
Now, in this scenario, everything loads, and ModuleA is recognized, but nothing appears on the screen.
However, if I change the <UserControl Grid.Row="0" prism:RegionManger .../> to <ItemsControl Grid.Row="0" prism:RegionManager .../>, I can see the content I've laid out in my ModuleA UserControl, but the content is all 'squished together'.
Does anyone have any ideas as to why this might be happening?

The default region adaptors in Prism don't support UserControl. You need to use ContentControl, ItemsControl or a Selector based control like a ComboBox to get out of the box support or write your own region adaptor.
Note: The region adaptor is used to add and remove controls from regions of a certain type of control when you interact with its regions.

Related

How to prevent the Content of a UserControl from being overridden?

I'm new to Windows 10 app development. I'm trying to embed my custom UserControl in a page in my application. For some reason, the content is being completely replaced by whatever I put inside it in the XAML page. To give a better explanation, here is the code:
AppView.xaml (the control)
<UserControl
x:Class="Sirloin.AppView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Sirloin"
xmlns:h="using:Sirloin.Helpers">
<SplitView x:Name="splitView" DisplayMode="CompactOverlay">
<SplitView.Pane>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!--The hamburger-->
<Button Click="OnHamburgerClicked" Grid.Row="0" Style="{StaticResource MenuButtonStyle}">
<Button.DataContext>
<local:MenuItem Symbol=""/>
</Button.DataContext>
</Button>
<!--Buttons just below the hamburger-->
<ListView x:Name="topView"
Grid.Row="1"
ItemTemplate="{StaticResource ListViewItemTemplate}"/>
<!--Buttons toward the bottom of the menu-->
<ListView x:Name="bottomView"
Grid.Row="3"
ItemTemplate="{StaticResource ListViewItemTemplate}"/>
</Grid>
</SplitView.Pane>
<SplitView.Content>
<!--Where I'd like the content specified in MainPage to appear-->
<Frame x:Name="frame" Background="White"/>
</SplitView.Content>
</SplitView>
</UserControl>
MainPage.xaml
<Page
x:Class="Sirloin.Example.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s="using:Sirloin"
xmlns:local="using:Sirloin.Example">
<s:AppView>
<Grid Background="White">
<TextBlock HorizontalAlignment="Center"
VerticalAlignment="Center"
Text="Hello, world!"/>
</Grid>
</s:AppView>
</Page>
When MainPage renders in the VS designer, it's as if the contents of my user control have been completely gutted out and replaced with whatever is specified in the main page. To give you an idea, here is a screenshot of the designer:
As you can see, there is no menu or SplitView or whatever I've put in my custom control; the only thing that's present is the TextBlock I've specified in the XAML for MainPage.
Anyway, why does this happen and what can I do to fix it?
EDIT: Found the solution I was looking for here, but Peter Duniho's answer has been accepted as it provides a better explanation of what's going on.
UserControl is a subclass of Control (which is similar to WPF's ContentControl). It can have only one child. So you are explicitly overriding the content yourself. By specifying a child element for your AppView in the Page XAML, you are setting the content of the control. This takes precedence over whatever content was specified in the UserControl's own XAML.
Unfortunately, it's not very clear what it is you expected to happen. Maybe you want to provide a property for additional content, which the AppView class can use to add to its own content. Or maybe you should be allowing the client code to provide a DataTemplate and some kind of data item object (e.g. model class), which is used in a ContentPresenter or similar in the AppView XAML.
But whatever you're trying to do, you'll have to do it without using, and overriding the current value of, the implicit Content property of the UserControl in the Page XAML.

How can i share same ViewModel between two views in WPF?

I have this view:
<Window x:Class="Ohmio.Client.PruebasView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Ohmio.Client"
Title="Pruebas" Height="284" Width="626">
<Window.DataContext>
<local:PruebasViewModel/>
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
<RowDefinition Height="40"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Label Content="Create View"/>
<Button Grid.Row="1" Content="Create child View" Click="Button_Click_1"></Button>
<ContentPresenter x:Name="ContentPrt" Grid.Row="2" Margin="5"></ContentPresenter>
</Grid>
My idea is to load a second view(child view) in the content presenter. Just for testing i'm doing this from code-behind:
this.ContentPrt.Content = new ModalViewModel();
So my question is: How can I make the new view(the one load on contentPresenter) share the same dataContext with PruebasView? (In this case, PruebasViewModel)
Thanks!
If I understood your question correctly, it's simple. Just pass PruebasViewModel to ContentPresenter as the data context.
<ContentPresenter x:Name="ContentPrt" DataContext={Binding} Grid.Row="2" Margin="5"></ContentPresenter>
I suppose that ModalViewModel is your child view class. So when you add it to the content presenter, your View becomes a part of your Visual Tree, so it automatically shares the DataContext of the main window.
Pratically WPF makes of the job for you: the content presenter's content will "see" the PruebasViewModel by its own.
EDIT
I did not read that you are using Caliburn Micro, but the idea does not change.

ContentControl not showing up without specifying width/height

I am using CefSharp in my WPF project. I'm adding the CefSharp.Wpf.WebView class to my MainWindow.xaml like so:
_webView = new WebView(url, _settings);
My XAML layout looks like this:
<Window x:Class="WPFContainer.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Test Project" Height="400" Width="930" Initialized="OnWindowInit" StateChanged="OnWindowStateChanged" Closing="OnWindowClose">
<DockPanel Name="MainDockPanel" Height="400" Width="930">
<Grid VerticalAlignment="Top" HorizontalAlignment="Left" ShowGridLines="True" Name="mainGrid" >
<Grid.ColumnDefinitions>
<ColumnDefinition Name="col1" Width="600" />
<ColumnDefinition Name="col2" Width="330"/>
</Grid.ColumnDefinitions>
</Grid>
</DockPanel>
</Window>
If I remove the Grid and add the webView to the DockPanel directly, it shows up just fine. But if I try to add the webView to col1 in the Grid, it doesn't display. It will display in the grid column if I specify a Width/Height, but HorizontalAlignment.Stretch doesnt work and I need 100% width and height!
My code for adding the webView to the Grid which doesn't work:
mainGrid.Children.Add(_webView);
Grid.SetColumn(_webView, 0);
The problem is that the Children property is populated in InitializeComponent. If you are adding children to the grid after it has been initialize, there is no property changed event for adding to the Children collection, as it is not an ObservableCollection. If you were to create a new collection I believe it would work programmatically, but that can be avoided by defining your webview in xaml (provided it has a paramaterless constructor). Then OnLoaded you can inject url and settings.

WPF Designer - Selecting element inside element

I am new to WPF so I would accept every piece of advice. My problem:
I use the Designer to put different components of the UI the way I like. And it's great. The problem came with this type of XAML structure:
<Window>
<Grid>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
/* Couple of buttons */
</Grid>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="223*"/>
<RowDefinition Height="99*"/>
</Grid.RowDefinitions>
<TabControl Margin="85,0,0,0" Padding="0,-5,0,0" Grid.RowSpan="2">
<TabItem Visibility="Collapsed">
<Grid>
/* textboxes and labels */
</Grid>
</TabItem>
<TabItem Visibility="Collapsed">
<Grid>
<Border Visibility="Hidden" Margin="136,66,76,66" Panel.ZIndex="10" BorderThickness="1" Width="320" Height="180">
<Grid Background="White">
<Grid.Effect>
<DropShadowEffect BlurRadius="10" RenderingBias="Quality" Direction="270" ShadowDepth="3" Opacity="0.1"/>
</Grid.Effect>
/* labels, textboxes and buttons */
</Grid>
</Border>
<TabControl Margin="0,0,0,38">
<TabItem>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
/* other elements */
</Grid>
</TabItem>
<TabItem>
<Grid>
<Grid>
/* checkboxes */
</Grid>
<Grid>
/* checkboxes */
</Grid>
/* labels */
</Grid>
</TabItem>
<TabItem>
<Grid>
</Grid>
</TabItem>
</TabControl>
/* buttons and labels */
</Grid>
</TabItem>
</TabControl>
</Grid>
</Grid>
Usually when I want to move something on the scene I just select it and drag / change it since it's a lot easier than just writing it in XAML. However, using the code above, if I want to select something from the inner TabControl I just can't. It automatically selects the one above which makes it a bit harder to manage the UI. My guess it's something to do with the Z-Index but I'm not really sure. I know it is probably a noobish question but it makes me struggle so I will be very thankful if someone explains this to me!
Thanks!
Well my guess is you have grids layered on top of each other that are capturing the clicks and preventing the selection of the elements below (z-order like you mention).
A few things to note
This isn't really specific to the designer, if you have Hit Testable elements layered on top of each, even if they look transparent, they will still capture the click and "steal" focus. You can do various things to prevent this, one option might be setting IsHitTestVisible=false on elements that you want clicks to "pass through" to elements below it. Another option is to set the Background of an element to {x:Null}, instead of the default (which is Transparent).
You can use the Document Outline panel probably on the left hand side of your VS window (or View | Other Windows | Document Outline) to navigate the Visual Tree...visually. This would allow you to "select" an item even it is underneath other items. However, even once it is selected in the document outline it won't be floated to the top of the design surface, so you won't be able to drag it around to position it, but you will be able to grab re-size handles and access the properties window for the selected element.
Ultimately you have to "hide" the element that is on top of it to get the drag positioning you want.
I had the same issue - I was busy laying out my app in the WPF designer, and things that I could move around before were unselectable and undraggable, with the TabControl always stealing focus.
The issue seems to be with the TabItem being Collapsed. I found it impossible to select anything inside a TabItem that had Visibility="Collapsed".
If you need to move things around try changing the visibility to Visible temporarily - I was able to move things around in the designer and then later set the visibility back again.
I haven't tested this particularly thoroughly and it's a bit of a kludge, but it worked well enough for me to do the layout.

What is this control called?

What is the name of the control that is highlighted blue?
I want to make this:
(source: deviantart.net)
It would be helpful if you found some link to a library. I've searched using many different names (TaskButton/TaskPanel/StackPanel) but I'm really off.
Thanks.
Please note that the second image is only a concept sketch, and that it's not a real application.
This is most likely a custom (user) control which has been created by composing a number of standard WPF controls. It could easily be constructed in WPF using a horizontal StackPanel with various Image, TextBlock and Button elements as its content
I do not believe that the control you are pointing to is a .NET or WPF control. Most Windows 7 user interface elements are still native C/C++ resources.
That said, it is relatively easy to replicate that behavior using WPF 4.0, through a ListBox with a custom ItemTemplate. Take a look at this question to get you started.
It looks rather like a CommandLink control to me, something that first appeared in Vista. It's never been exposed as a control for use in Windows Forms or WPF, but this question contains information on how to make it available for your own use:
I suppose it is a WPF user control, created specifically for this application. It looks like it consists of a Image, some TextBox controls and a Button which in turn contains an Image.
I don't know how that control is called but my bet it is it's a custom windows form control, here's a link to get you started
I got it. You can do this with the help of a simple button in WPF.
You have to embed another button and those images to that button.
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Grid>
<Button Height="38" Margin="12,49,83,0" Name="button1" VerticalAlignment="Top"></Button>
<Grid Height="32" Margin="113,48,80,0" VerticalAlignment="Top">
<Grid.RowDefinitions>
<RowDefinition Height="13*" />
<RowDefinition Height="19*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="16*" />
<ColumnDefinition Width="8*" />
<ColumnDefinition Width="43*" />
<ColumnDefinition Width="12*" />
<ColumnDefinition Width="6*" />
</Grid.ColumnDefinitions>
<Button Margin="0,6,0,0" Name="button2" HorizontalAlignment="Left" Width="35" Grid.ColumnSpan="3" Grid.RowSpan="2">Button</Button>
<Button Grid.ColumnSpan="2" Grid.RowSpan="2" Margin="17,6,3,0" Name="button3" Grid.Column="2">Button</Button>
</Grid>
</Grid>
</Window>

Categories

Resources