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

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.

Related

WPF goes to the top of each pages when navigating/reloading page

I'm very new to WPF .net 5.0 framework. Every time I navigate to a different page in a frame, it maintains the scroll position instead of going back to the top of the page. May I know if there is a way to make sure that it goes to the top of the page every time I navigate? Thank you!
this is the xaml
<ScrollViewer Height="1000" Width="1000" HorizontalScrollBarVisibility="Auto">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="23*"/>
<RowDefinition Height="477*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<TextBlock HorizontalAlignment="Left" Margin="10,0,0,0" TextWrapping="Wrap" VerticalAlignment="Center" FontWeight="Bold" Foreground="#FF5B5858"><Run Language="en-sg" Text="ADD NEW APPLICATION"/></TextBlock>
</Grid>
<Grid Grid.Row="1" Margin="0,10,0,0">
<Border CornerRadius="0,0,30,0" BorderThickness="1">
<Frame x:Name="wizardFrame" Content="Frame" HorizontalAlignment="Center" Width="1002" Margin="0,9,0,471" NavigationUIVisibility="Hidden"/>
</Border>
</Grid>
</Grid>
</ScrollViewer>
This is the code behind
wizardFrame.NavigationService.Navigate(new LocationPage1());
This is what i use to navigate to different pages in a frame
this.NavigationService.Navigate(new GenerateApplicationNumberPage2());
Your issue is that the ScrollViewer has no relation to the Frame, so it won't react to the Frame navigating.
In order to fix that, I see two solutions (pick one):
You name your ScrollViewer (e.g: mainScroll), and in the code-behind, you subscribe to the Navigated event of your Frame, so as to call ScrollViewer.ScrollToTop(), as suggested in a comment.
// Somewhere in the constructor after InitializeComponent();
wizardFrame.Navigated += (_, __) => mainScroll.ScrollToTop();
You remove the ScrollViewer from your main page, and add one as the root element in the XAML of each Page (LocationPage1, GenerateApplicationNumberPage2, and any other page). It will work because you create a new page each time you navigate (which isn't very good for resource management, but this is not the subject here).
The difference will be that the TextBlock with "ADD NEW APPLICATION" will always be visible above the Pages instead of being inside the ScrollViewer.
<Page x:Class="Namespace.LocationPage1">
<ScrollViewer Height="1000" Width="1000">
<!-- Your page content here -->
</ScrollViewer>
</Page>

Changing size of User Control

I'm having a problem with determining which element is responsible for a size misalignment. Here is a picture to illustrate it: click here to see it
The light grey area is the element size which I am trying to change, but cannot. The overall area is a User Control, the area inside the Tab is a WPF (as an element Host). I've tried changing both, but with no effect on the grey area (the other tabs are also affected by this). Here is the code for the hosted element (WPF):
<UserControl x:Class="SlideAnalyzer.DisplayAnalysis"
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:SlideAnalyzer"
mc:Ignorable="d"
d:DesignHeight="150.8" d:DesignWidth="201.2">
<Grid Name="displayGrid" Height="64" VerticalAlignment="Bottom" HorizontalAlignment="Center" Width="160" Margin="10,0,31.6,9.4" RenderTransformOrigin="0.496,0.94">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Expander x:Name="expander" Grid.Row="0" Header="Titel zu lang" HorizontalAlignment="Left" VerticalAlignment="Top" Width="180" Background="Red" Margin="-10,-56,0,0">
<Grid Background="AliceBlue">
<TextBlock TextWrapping="Wrap"
Margin="5"><Run Text="This is some text content."/></TextBlock>
</Grid>
</Expander>
</Grid>
The host itself is a normal User Control. I cannot seem to get the right size of the hosted element so that the preview really reflects reality (because when I run the Add-In, the size of the WPF differs)
I tried changing the Properties of the UserControl and I found that AutoSize has a big impact when True (by default False)
Thanks!

WPF UserControl Not Displaying

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.

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.

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