NavigationView Item with extra content on right side - c#

I have a NavigationView in my app. I want to add counters/badges to some of the items. But whatever I do, the badge always stays right next to the label. See the image below (on the top is what I have, on the bottom what I want to achieve)
The code I'm currently using is the following:
<NavigationViewItem Icon="Mail">
<NavigationViewItem.Content>
<RelativePanel HorizontalAlignment="Stretch">
<TextBlock RelativePanel.AlignLeftWithPanel="True">Inbox</TextBlock>
<local:Badge RelativePanel.AlignRightWithPanel="True" BadgeText="30"/> <!-- can be replaced with a simple "TextBlock" -->
</RelativePanel>
</NavigationViewItem.Content>
</NavigationViewItem>
(You can subsitute the Badge control with a simple TextBlock)

The problem is that RelativePanel can't get SplitViewOpenPaneThemeLength automatically. so we need specific the width for RelativePanel. As we known SplitViewOpenPaneThemeLength is 320, and SplitViewCompactPaneThemeLength is 48. so the
width of NavigationViewItem.Content is 320-48 = 272. Please refer the following xaml code.
<RelativePanel HorizontalAlignment="Stretch" Width="{ThemeResource SplitViewOpenPaneThemeLength}">
<TextBlock RelativePanel.AlignLeftWithPanel="True">Inbox</TextBlock>
<TextBlock RelativePanel.AlignRightWithPanel="True" Text="30" Margin="0,0,48,0"/>
<!-- can be replaced with a simple "TextBlock" -->
</RelativePanel>

Related

ReactiveUI + WPF: ViewModelViewHost does not stretch inside its parent

I'm trying to get a fresh little reactUI WPF app up and running. However ViewModelViewHost causes me problems. It does not fill the widow but stays at its minimum required measures. (as calculated off of its children)
I have this bit of XAML in my MainWindow.xaml:
<Grid Grid.Row="1" Name="WorkArea">
<reactiveUi:ViewModelViewHost ViewModel="{Binding .}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0" DataContext="{Binding DocVm}">
<reactiveUi:ViewModelViewHost.DefaultContent>
<Label Content="no file" FontStyle="Italic" FontSize="33" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</reactiveUi:ViewModelViewHost.DefaultContent>
</reactiveUi:ViewModelViewHost>
</Grid>
So there is a grid in the MainWindow and the middle part shall be occupied by the ViewModelViewHost hence applying Horizontal and VerticalAlignment. I also tired getting rid of the second grid, but no difference. What actually happens (as seen in Snoop) is: The ViewModelViewHost complies to the stretch setting but its templated part PART_CurrentContentPresentationSite does not comply. It stays at Left + Top. What should I do, how was this intended?
Replace the template...
BTW. It also seems not to be enough just to set the ViewModel-property in order to have the view binding at the view model. You also have to set the DataContext.
You need to use the HorizontalContentAlignment and VerticalContentAlignment and set those to stretch.

Display multiline DynamicResource Label

I wish to add a Label in WPF that displays string from two different DynamicResources.
I want each DynamicResource to be on a new line.
My existing code is:
<Label x:Name="MyTextDisplay"
Grid.Row="3"
Grid.ColumnSpan="2"
Background="Red"
BorderBrush="Blue"
BorderThickness="1"
Margin="2, 2, 2, 2">
<TextBlock TextWrapping="Wrap" Text="{DynamicResource MyTextLine1}" Grid.ColumnSpan="2"/>
</Label>
I have another DynamicResource called MyTextLine2 that I want to display below MyTextLine1 but in the same Label.
How can I do this?
I have looked at these examples here but they dont display on new lines: How to bind multiple values to a single WPF TextBlock?
I faced the same problem and finally I found a solution.
Just use \r\n linebreak instead of just \n.
So, your resourse must look like:
<system:String x:Key="MyText" xml:space="preserve">Line 1
Line 2</system:String>
I realy don't know why this notation must be used only for dynamic resources, but it works for me

How to set button in side stackpanel to right edge in windows 10 universal app development

I an new to windows app development,i searched for this but not found any where.I need the button at right edge and Stretch the textbox till buttons start.But I am unable to set the button to Right edge.
How to acheve this.
A stackpanel works like a container. If you define layout properties on your stackpanel, then the objects inside your stackpanel cannot be displayed outside of the stackpanel's limits.
For example :
If I set my row and column number in my stackpanel,
<StackPanel Grid.Row="0" Grid.Column="2" Name="Version" Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Top">
<Label Grid.Column="4" Grid.Row="6" Name="Ver" Content="V." HorizontalAlignment="Right" />
<TextBlock Name="Vers" Text="1.0" TextAlignment="Right" />
</StackPanel>
Then the row/column properties set on my label are ignored and the 'HorizontalAlignment="Right"' will place my label on the right side of the stackpanel, not the grid.
A solution may be to remove your button from your stackpanel, you are then free to place your button anywhere on the grid.
Another solution can be to expand your stackpanel's limits.
To do so, you can use the Grid.ColumnSpan property or simply set your stackpanel on the right of the grid.
Hope that helped.

How to bind to a control's literal actual width (including its margins)?

According to some folks, the actual width is obtained using ActualWidth attribute as shown in the example below. It makes sense but I seem to experience contradicting behavior.
<Canvas Width="{Binding ActualWidth,ElementName=Expy}">
<Expander x:Name="Expy"
HorizontalAlignment="Left"
Margin="0,0,0,0"
VerticalAlignment="Top" ...>
...
</Expander>
</Canvas>
In the setup above, the behavior is consistent with the expectations and, although tightly squeezed together, the next element in the panel containing the canvas is not overlapped by it's predecessor.
However, if I change the margins to a bit wider, I can clearly see that the canvas intrude on the next element, estimatingly by the same number of pixies that I requested in the margin attribute. So it'd appear that the ActualWidth isn't the actual width but the width without the margin.
Am I confusing something here and if so, what?
How to obtain and bind to the actaully actual, rendered width?
The linked answer says:
ActualWidth accounts for padding and margins ...
This is incorrect. The ActualWidth includes only the padding, not the margin (same with ActualHeight).
A comment that has been left on that answer by somebody else provides the appropriate correction.
This XAML code illustrates the issue:
<Window x:Class="..."
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel>
<TextBlock x:Name="First" Text="Some text" Padding="10" Margin="0,0"
HorizontalAlignment="Left" Background="Yellow" />
<TextBlock Text="{Binding ActualWidth, ElementName=First}" />
<TextBlock x:Name="Second" Text="Some text" Padding="10" Margin="10,0"
HorizontalAlignment="Left" Background="LimeGreen" />
<TextBlock Text="{Binding ActualWidth, ElementName=Second}" />
</StackPanel>
</Window>
If you run this you will see that both of the "Some text" text blocks have the same ActualWidth value despite the second one having horizontal margins applied to it.
You asked how you could take this into account. There is no way of doing this through binding because the ActualWidth property doesn't include the margin as already stated. What you can do is apply the margin to the parent element (the canvas) instead of applying it to the expander.
In other words, instead of doing this:
<Canvas Width="{Binding ActualWidth,ElementName=Expy}">
<Expander x:Name="Expy" ... Margin="10" ... >
...
</Expander>
</Canvas>
do this:
<Canvas Width="{Binding ActualWidth,ElementName=Expy}" Margin="10">
<Expander x:Name="Expy" ... >
...
</Expander>
</Canvas>
Yes Konrad. You are confusing.
Whenever we mean Actual(Height/Width), it is the rendered one. You were correct in that. However, Actual(Height/Width) values gets initialized after the WPF Layout process which includes Measure and Arrange stages and that is something you need to understand first to get to the real cause of the problem.
At first, Binding anything with Actual values will never give you desired results because by doing this you are violating WPF Layout chain. As per WPF Layout stages, in Measure stage WPF gets the specified size (for e.g. values specified in height and width) for each control in the layout and then in the Arrange stage it actually allocates controls to the layout in the best possible way. The size specified is subject to vary after the Arrange stage.
Also, it should be noted that Actual parameters include rendered size plus padding value (but not margin). In your example, I guess the other panel next to the Expander control is the reason behind the problem you reported. I can confirm only when I see the entire layout.
But as a precautionary measure, you can always stop using Actual parameters for bindings. You can definitely get it worked out using Width and Height values for binding.
You cannot include the margin to your ActualWidth. A solution for this would be to use DesiredSize.Width or DesiredSize.Height. This will take into account the Margin. But it's a UIElement.

remove a element from a StackPanel and add it to other StackPanel

is it possible to remove a item e.g. a TextBlock from a StackPanel and add it to a other StackPanel?
My XAML Code looks like this:
<StackPanel x:Name="PanelStack1" VerticalAlignment="Bottom" Margin="0,0,0,86">
<Rectangle x:Name="RecX" />
</StackPanel>
<StackPanel x:Name="PanelStack2" VerticalAlignment="Bottom" Margin="0,0,0,86" />
I want to move the RecX from the PanelStack1 to PanelStack2 via my C# Code. Is this possible?
This is just a small example, in my real code there are many elements which have to been moved.
Try this in your code behind:
PanelStack1.Children.Remove(RecX);
PanelStack2.Children.Add(RecX);

Categories

Resources