Windows 10 Pro 64, VS 2019 Community, WPF App
I have an app that has a UserControl with two members, each of which is a UserControl that contains a header which is 2 -3 lines of text, with a ListBox below it. My objective is to set the height of the one header to the height of the other, and I've chosen to bind the one to the other to accomplish that. But, it appears as if my RelativeSource is not resolving, which results in trying to set the height to a NaN, which, of course, does not change it. I've tried many different ways to express the RelativeSource, and none of them has worked. Here's the latest:
Here's the main window:
<Window x:Class="MyApp.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:MyApp"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<local:MyParentControl x:Name="Daddy"/>
</Grid>
</Window>
And the Parent control that contains the two children:
<UserControl x:Class="MyApp.MyParentControl"
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:MyApp"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<StackPanel Orientation="Horizontal">
<local:MySonControl x:Name="Sonny"/>
<local:MyDaughterControl x:Name="Girlie"/>
</StackPanel>
</Grid>
</UserControl>
The first child control:
<UserControl x:Class="MyApp.MySonControl"
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:MyApp"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Vertical" x:Name="Header">
<TextBlock Text="Vertical space" HorizontalAlignment="Center"/>
<TextBlock Text="Sonny's Stuff" HorizontalAlignment="Center"/>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Column A" Margin="5,5,5,5"/>
<TextBlock Text="Column B" Margin="5,5,5,5"/>
<TextBlock Text="Column C" Margin="5,5,5,5"/>
</StackPanel>
</StackPanel>
<ListBox x:Name="Stuff"/>
</StackPanel>
</Grid>
</UserControl>
And the second, which contains the binding statement:
<UserControl x:Class="MyApp.MyDaughterControl"
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:MyApp"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Vertical" x:Name="Header"
Height="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=local:MyParentControl}, Path=Sonny.Header.ActualHeight}"
>
<TextBlock Text="Girlie's Stuff" HorizontalAlignment="Center"/>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Column A" Margin="5,5,5,5"/>
<TextBlock Text="Column B" Margin="5,5,5,5"/>
<TextBlock Text="Column C" Margin="5,5,5,5"/>
</StackPanel>
</StackPanel>
<ListBox x:Name="Stuff"/>
</StackPanel>
</Grid>
</UserControl>
I have not touched the code-behind, it's just as VS generated it.
Here's what it displays:
What we should see is that the right header is the same height as the left, but as you can tell, that is not the case.
I get the following error message in my output window, which I take to mean that it's not resolving the RelativeSource:
System.Windows.Data Error: 40 : BindingExpression path error: 'Sonny' property not found on 'object' ''MyParentControl' (Name='Daddy')'. BindingExpression:Path=Sonny.Header.ActualHeight; DataItem='MyParentControl' (Name='Daddy'); target element is 'StackPanel' (Name='Header'); target property is 'Height' (type 'Double')
Any ideas of what I'm doing wrong?
Use a SharedSizeGroup to sync the heights of the rows, and remove the StackPanels in favor of Grid rows:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" SharedSizeGroup="HeaderGroup"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Grid.Row="1" Text="Girlie's Stuff" HorizontalAlignment="Center"/>
<StackPanel Grid.Row="2" Orientation="Horizontal">
<TextBlock Text="Column A" Margin="5,5,5,5"/>
<TextBlock Text="Column B" Margin="5,5,5,5"/>
<TextBlock Text="Column C" Margin="5,5,5,5"/>
</StackPanel>
<ListBox Grid.Row="3" x:Name="Stuff"/>
</Grid>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" SharedSizeGroup="HeaderGroup"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Text="Vertical space" HorizontalAlignment="Center"/>
<TextBlock Grid.Row="1" Text="Sonny's Stuff" HorizontalAlignment="Center"/>
<StackPanel Grid.Row="2" Orientation="Horizontal">
<TextBlock Text="Column A" Margin="5,5,5,5"/>
<TextBlock Text="Column B" Margin="5,5,5,5"/>
<TextBlock Text="Column C" Margin="5,5,5,5"/>
</StackPanel>
<ListBox Grid.Row="3" x:Name="Stuff"/>
</Grid>
<Grid IsSharedSizeScope="True">
<StackPanel Orientation="Horizontal">
<wpfApp2:MySonControl x:Name="Sonny"/>
<wpfApp2:MyDaughterControl x:Name="Girlie"/>
</StackPanel>
</Grid>
Results in:
Depending on what the contents of the two child control will be, I strongly suggest to only use one child UserControl and use MVVM to populate it with different data. This will remove the need to maintain two basically identical controls.
Related
I'm brand new WPF so I may be missing something obvious. I've got a TextBox in the designer, that looks fine and is visible, however, when running the app it isn't visible while the other elements are still visible.
Designer:
Application:
Xaml:
<Window x:Class="Windows.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:Windows"
mc:Ignorable="d"
Title="UniPaste for Windows" Height="450" Width="800"
Background="#333">
<Grid>
<TextBlock TextWrapping="Wrap" Text="UniPaste for Windows" Margin="0,0,0,348" TextAlignment="Center" VerticalAlignment="Center" Foreground="White" FontSize="32" FontFamily="Consolas Bold"/>
<TextBlock TextWrapping="Wrap" Text="Email" Margin="0,90,0,0" TextAlignment="Center" VerticalAlignment="Top" Foreground="White" FontSize="24" FontFamily="Consolas"/>
<TextBox Name="Email" Margin="340,123,340,290" Background="White" Height="23" TextChanged="EmailChanged"/>
</Grid>
</Window>
Take advantage of the Grid component and its row and column definitions to align the elements you want.
What was happening is that at runtime the textbox had no line to attach to
<Window x:Class="WpfApp1.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:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800"
Background="#333">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0"
Margin="0 25 0 0"
TextWrapping="Wrap"
Text="UniPaste for Windows"
TextAlignment="Center"
VerticalAlignment="Center"
Foreground="White"
FontSize="32"
FontFamily="Consolas Bold"
/>
<TextBlock Grid.Row="1"
Margin="0 25 0 0"
TextWrapping="Wrap"
Text="Email"
TextAlignment="Center"
VerticalAlignment="Top"
Foreground="White"
FontSize="24"
FontFamily="Consolas"/>
<TextBox Grid.Row="2"
Name="Email"
Margin="0 25 0 0"
HorizontalAlignment="Center"
Background="White"
Height="23" Width="100"
TextChanged="EmailChanged"
/>
</Grid>
Runtime Window
Working on IoT Project using Windows IoT core. So Far Images, Videos and Audios are able to display on the Display. Need to add a scrolling Text at the bottom
The Code Developed so far XAML is:
<Page
x:Class="Digital_Notiec_Board_V1._2.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Digital_Notiec_Board_V1._2"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="#FF222222" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Image x:Name="imageInstance" Visibility="Collapsed" />
<MediaElement x:Name="audioInstance" Visibility="Collapsed" />
<MediaElement x:Name="videoInstance" Visibility="Collapsed" />
<TextBlock x:Name="ScrollText" HorizontalAlignment="Left" Height="63" Margin="0,1017,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Width="1910" FontSize="36" Foreground="White"/>
<!--
<WebView x:Name="webViewInstance" Visibility="Collapsed"/>
-->
</Grid>
Please help me out with suggestion. If possible any Base to check On.
Thanks in advance
You can use ScrollViewer to represent the text area.Please refer to following XAML codes.To make your app responsive and adaptive,it is a good choice to use XAML properties and layout panels.Please reference Define page layouts with XAML.
<Page
x:Class="Digital_Notiec_Board.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Digital_Notiec_Board"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="#FF222222" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition MaxHeight="200"></RowDefinition>
<RowDefinition MaxHeight="200"></RowDefinition>
<RowDefinition MaxHeight="200"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Image x:Name="imageInstance" Visibility="Collapsed" Grid.Row="0"/>
<MediaElement x:Name="audioInstance" Visibility="Collapsed" Grid.Row="1"/>
<MediaElement x:Name="videoInstance" Visibility="Collapsed" Grid.Row="2"/>
<ScrollViewer Grid.Row="3">
<TextBlock x:Name="ScrollText" TextWrapping="Wrap" Foreground="White" Text="TextBlock" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollMode="Auto">
</TextBlock>
</ScrollViewer>
</Grid>
I have a TextBlock that is not wrapping and thinks it has an infinite width. I have tried to bind it to the actualWidth of the Grid and/or UserControl, but both widths come as more than 8000. I have tried disabling the HorizontalScrollBarVisibility in the parent view, but that does not work either. I have also read all question in SO that are related to mine and none of the suggestions seems to work.
<UserControl x:Class="Civica.UI.CurrentUserMenu.Views.ClassName"
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"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="1200">
<UserControl.Resources>
<ResourceDictionary>
<SolidColorBrush x:Key="SeparatorBrush" Color="#66848484" />
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<ScrollViewer x:Name="Viewer" BorderThickness="0" Grid.Column="1" Grid.Row="1" Margin="0,0,0,0" Padding="0"
VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch">
<Grid Background="White" HorizontalAlignment="Left" x:Name="UserControl">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Border BorderThickness="0,0,0,1" BorderBrush="{StaticResource SeparatorBrush}" Grid.Row="0">
<TextBlock Text="Text" Margin="0" FontWeight="Black" />
</Border>
<TextBlock Margin="5" Text="{Binding TextProperty}" TextWrapping="Wrap" Grid.Row="1"/>
</Grid>
</ScrollViewer>
</Grid>
</UserControl>
EDIT:
This is the code for the parent view:
<UserControl x:Class="Civica.UI.Ribbon.Views.ViewName"
d:DataContext="{d:DesignInstance Type=ViewMOdelName}"
d:DesignHeight="120"
d:DesignWidth="600"
mc:Ignorable="d">
<Grid ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<telerik:RadRibbonView x:Name="RadRibbon"
Title="Title"
ApplicationButtonContent="Content"
ApplicationMenu="{Binding PropertyName}"
ApplicationName="{Binding PropertyName}"
MinimizeButtonVisibility="Visible"
SelectionChanged="SelectionChanged" ScrollViewer.HorizontalScrollBarVisibility="Disabled"/>
</Grid>
</UserControl>
It is the RadRibbonView that contains the first view.
The issue was a style that was being applied by the parent view and specifically a Telerik object. The solution was to find that style, decompile it and copy is to one of our files and change a scrollviewer to a border.
I created this user control
<UserControl x:Class="POS1.Windows.Controles.txttransparente"
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"
Height="auto" Width=" auto"
>
<Border BorderBrush="Yellow" Background="Transparent" CornerRadius="10,10,10,10" Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2">
<TextBox Name="txt1" Background="Transparent" BorderBrush="Black" BorderThickness="3" Text="Usuario" FontSize="20" FontWeight="ExtraBold" ></TextBox>
</Border>
</UserControl>
When I add it to a Window,
<Controls:MetroWindow
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
xmlns:Custom="http://modernwpf" xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
x:Class="POS1.MainWindow"
xmlns:txt="clr-namespace:POS1.Windows.Controles"
Title="MainWindow" Height="292" Width="535" AllowsTransparency="True" WindowStyle="None"
>
<Grid>
<Grid.RowDefinitions >
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions >
<ColumnDefinition Width="133*"/>
<ColumnDefinition Width="134*"/>
<ColumnDefinition Width="135*"/>
<ColumnDefinition Width="133*"/>
</Grid.ColumnDefinitions>
<Border Grid.ColumnSpan="4" Grid.RowSpan="7" CornerRadius="40,50,60,70">
<Border.Background>
<ImageBrush ImageSource="pack://siteoforigin:,,,/Resources/b.jpg"/>
</Border.Background>
</Border>
<Border BorderBrush="Yellow" Background="Transparent" CornerRadius="10,10,10,10" Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2">
<TextBox Background="Transparent" BorderBrush="Black" BorderThickness="3" Text="Usuario" FontSize="20" FontWeight="ExtraBold" ></TextBox>
</Border>
<TextBox Grid.Row="3" Grid.Column="1" Grid.ColumnSpan="2" Text="Contraseña" FontSize="20" FontWeight="ExtraBold" ></TextBox>
<Button Grid.Row="5" Grid.Column="1" Content="Aceptar" FontSize="12" FontWeight="ExtraBold" ></Button>
<Button Grid.Row="5" Grid.Column="2" Content="Olvidé contraseña" FontSize="12" FontWeight="ExtraBold" ></Button>
<txt:txttransparente Content=" Hola Mundo" Grid.Row="6" Grid.Column="1" Grid.ColumnSpan="2" ></txt:txttransparente>
</Grid>
</Controls:MetroWindow>
as you see I could not modify the txt1.Text, so I have instead used Content="hola mundo"
However this sees it as above, but not as similar to the button usuario.
Without explicitly navigating the control's visual tree, the elements in your UserControl need for you to implement mechanism to pass data from client code using your control to the elements contained within. A common strategy for doing this is to simply declare a property on your UserControl type itself, and then bind the appropriate member in the control's tree to that property.
For example:
class txttransparente : UserControl
{
public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
"Text", typeof(string), typeof(txttransparente));
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
}
Then in your XAML for the UserControl:
<UserControl x:Class="POS1.Windows.Controles.txttransparente"
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:POS1.Windows.Controles"
mc:Ignorable="d"
Height="auto" Width=" auto">
<Border BorderBrush="Yellow" Background="Transparent" CornerRadius="10,10,10,10"
Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2">
<TextBox Name="txt1" Background="Transparent" BorderBrush="Black"
BorderThickness="3"
Text="{Binding Text,
RelativeSource={RelativeSource AncestorType={x:Type local:
txttransparente}}}"
FontSize="20"
FontWeight="ExtraBold"/>
</Border>
</UserControl>
Note the change not only in the binding for the TextBox.Text property there, but also the addition of the xmlns:local declaration, so that the binding can find the parent UserControl object where the property exists.
These changes create the property, and connect it to the Text property of the control's TextBox element.
Then finally, where you use the UserControl, you simply set the Text property (instead of Content):
<txt:txttransparente Text="Hola Mundo" Grid.Row="6" Grid.Column="1" Grid.ColumnSpan="2"/>
I have a User Control like this:
<UserControl x:Class="MySample.customtextbox"
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="20" d:DesignWidth="300">
<Grid>
<TextBox x:Name="Ytextbox" Background="Yellow"/>
</Grid>
And I use this control in a window and set tab orders...but when my window is loaded, the tab order is not working correctly!!!
my window code:
<Window xmlns:my="clr-namespace:MySample" x:Class="MySample.window"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="window" Height="300" Width="600">
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<my:customtextbox Grid.Column="1" KeyboardNavigation.TabIndex="0" InfoText="{Binding msg}" Height="20"/>
<TextBox Grid.Column="3" KeyboardNavigation.TabIndex="1" Text="{Binding msg}" Height="20" Background="Gold"></TextBox>
<my:customtextbox Grid.Row="1" Grid.Column="1" KeyboardNavigation.TabIndex="2" InfoText="{Binding msg}" Height="20"/>
<TextBox Grid.Column="3" Grid.Row="1" Text="{Binding msg}" Height="20" KeyboardNavigation.TabIndex="3" Background="Gold"></TextBox>
</Grid>
By default, WPF reads all the controls, inside and outside your UserControl, at the same tab level. Since the controls inside your UserControl do not have a TabIndex specified, they get tabbed to last after the first tab cycle.
The workaround I usually use is to set the IsTabStop="False" on my UserControl (to prevent tabbing onto the UserControl itself), and then inside the UserControl use a TemplateBinding to bind to the inner Controls TabIndex to the UserControl's TabIndex
<TextBox x:Name="Ytextbox" Background="Yellow"
TabIndex="{Binding Path=TabIndex,
RelativeSource={RelativeSource AncestorType={x:Type local:customtextbox}}}"/>
and
<my:customtextbox IsTabStop="False" KeyboardNavigation.TabIndex="0"
Grid.Column="1" InfoText="{Binding msg}" Height="20"/>