How to get the value of the margin of a border? - wpf

I'm a beginner in WPF and have to add functionality to someone's user interface. Here's part of the code.
<Border BorderBrush="Black" BorderThickness="1" Grid.Row="1" >
<Grid Grid.Row="0">
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition Width="{Binding ElementName=passFailIndicator, Path=Width}"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Border Background="Black" local:StretchPanel.Proportion="1" Name="imageBorder" Grid.Column="0">
<Border BorderThickness="1" Margin="2" BorderBrush="Green" HorizontalAlignment="Left" VerticalAlignment="Top" Width="{Binding ElementName=imageBorder, Path=Width}">
<Grid Width="{Binding ElementName=imageBorder, Path=Width}">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="{Binding ElementName=imageSelectExpander, Path=Width}"/>
</Grid.ColumnDefinitions>
<Image Grid.Column="0" x:Name="image" Source="{Binding DisplayImage, Mode=OneWay}" VerticalAlignment="Top" Stretch="Uniform" HorizontalAlignment="Left" StretchDirection="Both" MouseMove="image_MouseMove" />
<TextBlock Name="pxPos" Text="mouse position" HorizontalAlignment="Right" VerticalAlignment="Bottom" MaxHeight="20" Foreground="Aqua"></TextBlock>
<Expander Grid.Column="1" VerticalAlignment="Top" Name="imageSelectExpander">
<ComboBox x:Name="imageSelect" ItemsSource="{Binding AvailableImages, Mode=OneWay}" SelectedIndex="{Binding ImageSelect, Mode=TwoWay}" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Margin="4" Padding="4" MaxHeight="40"></ComboBox>
</Expander>
</Grid>
</Border>
</Border>
<Border x:Name="passFailIndicator" Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Center" Width="100" Height="100">
<Viewbox Stretch="Uniform" >
<Path Style="{Binding TestResult, Mode=OneWay, Converter={StaticResource testResultToPathStyle}}" Margin="2" />
</Viewbox>
</Border>
</Grid>
</Border>
I'm trying to access the Margin="2" on line 10. When I use this.imageBorder.Margin, I get {0,0,0,0}. How would I get the 2 (of course, this value may change)?
thanks
edit:
FrameworkElement fe = (FrameworkElement)this.imageBorder.Child;
pxPos.Text = (string.Format("x:{0} y:{1}", (int)((double)(pt.X - fe.Margin.Left) * (double)this.image.Source.Width / this.image.ActualWidth), (int)((double)(pt.Y - fe.Margin.Top)*(double)this.image.Source.Height / this.image.ActualHeight)));

The Border labeled imageBorder does not have its Margin property set to anything, so you are getting the default Margin, which is 0.
To get the Margin property of the Border inside your named border, either give it an x:Name so you can access it in code behind, or look in imageBorder.Child property to find the child Border object, then cast it to a FrameworkElement to get its Margin property.
As for why you're getting {0,0,0,0}, the Margin property is of type Thickness, which consists of properties for Left, Top, Right, and Bottom. If you set a margin to a single value, such as 2, it automatically converts that to a Thickness object with all 4 of its properties set to 2.

Related

How can I turn on both vertical and horizontal borders for the itemTemplate Control?

I created the item template control and set its border thickness and color in Data Template. This is my ItemTemplate code:
<ItemsControl x:Name="VimshottariDasha" Margin="-10,83,-124,-267" FontSize="16" Grid.ColumnSpan="3" BorderThickness="0">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderThickness="1" BorderBrush="DimGray">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="Col1" />
<ColumnDefinition SharedSizeGroup="Col2" />
<ColumnDefinition SharedSizeGroup="Col3" />
</Grid.ColumnDefinitions>
<Button Background="Transparent" BorderThickness="0" x:Name="DashaButton" Grid.Column="0" Content="{Binding rulerName}" Command="{Binding SelectedDasha}" CommandParameter="{Binding Content, RelativeSource={RelativeSource Self}}"/>
<TextBlock Grid.Column="1" Text="{Binding rulerStartDate, StringFormat=dd-MMM-yyyy HH:mm:ss}" />
<TextBlock Grid.Column="2" Text="{Binding rulerEndDate, StringFormat=dd-MMM-yyyy HH:mm:ss}"/>
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
How do I show both vertical and horizontal borders regardless of stack orientation?
The same thing happens in another itemTemplate but in reverse, whose stack orientation is set to Horizontal. I can see vertical borders in the second item Control but no Horizontal borders.
This is the current Output, it has horizontal Borders inside but no vertical ones(Stack orientation is vertical by default)
This is second ItemControl with horizontal stack orientation it is missing horizontal borders.
Thanks.
First go through this link to understand how to add border around TextBlock.
You can also use Label instead of TextBlock to add border.
Now look into modified code:
ItemsControl Grid.Row="0" x:Name="VimshottariDasha" Margin="10" FontSize="16" Grid.ColumnSpan="3" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<!--<Border BorderThickness="1" BorderBrush="DimGray">-->
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="Col1" />
<ColumnDefinition SharedSizeGroup="Col2" />
<ColumnDefinition SharedSizeGroup="Col3" />
</Grid.ColumnDefinitions>
<Button Background="Transparent" BorderThickness="1" x:Name="DashaButton" Grid.Column="0" Content="{Binding rulerName}" />
<Border Grid.Column="1" BorderThickness="1" BorderBrush="Blue">
<TextBlock Text="{Binding rulerStartDate, StringFormat=dd-MMM-yyyy HH:mm:ss}" />
</Border>
<Label BorderThickness="1" BorderBrush="Bisque" Grid.Column="2" Content="{Binding rulerEndDate, StringFormat=dd-MMM-yyyy HH:mm:ss}"/>
</Grid>
<!--</Border>-->
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
A WPF Border control only draws the border along its outer edges. [It is possible to turn of one or more edges by setting its BorderThickness.]
If you want to create border lines between individual controls, you either have to use multiple Border elements, or manually draw the internal lines yourself.
For example
<Border HorizontalAlignment="Center" VerticalAlignment="Center" BorderBrush="Green" BorderThickness="2" >
<Grid Height="24" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="5" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="5" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Column 1" VerticalAlignment="Center" />
<TextBlock Grid.Column="2" Text="Column 2" VerticalAlignment="Center" />
<TextBlock Grid.Column="4" Text="Column 3" VerticalAlignment="Center" />
<Path Stroke="Red" StrokeThickness="1" Data="M 0,0 M 2,2 M 1,0 L 1,2" Stretch="Fill" Grid.Column="1" />
<Path Stroke="Red" StrokeThickness="1" Data="M 0,0 M 2,2 M 1,0 L 1,2" Stretch="Fill" Grid.Column="3" />
</Grid>
</Border>

Make textbox width automatically changable in Stackpanel which is in Border, WPF

I wanted to put Button in TextBox, but as I found it's not possible so I decided to do something like this:
Xaml for this looks as shown below:
<Border Grid.Row="4" Grid.Column="2" Margin="10,0,10,0"
BorderBrush="Gray" BorderThickness="1">
<StackPanel Orientation="Horizontal" Margin="0,0,0,0">
<TextBox BorderBrush="LightGray" BorderThickness="1" Text="{Binding WaybillNumber}"
Width="245"/>
<Button Content="*" Width="15" BorderThickness="1"/>
</StackPanel>
</Border>
The problem I have is that, when I resize my window (decreasing width) my Button dissapears:
I want it to behave as DateTimePicker does. I have tried many ways to make TextBox width auto adjustable ( * in width isn't correct input, auto decreases width of TextBox, I also tried to define style resource in StackPanel resources for TextBox width, but it doesn't work too), but Haven't found correct way yet.
Replace the StackPanel with a Grid:
<Border Margin="10,0,10,0" BorderBrush="Gray" BorderThickness="1">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBox BorderBrush="LightGray" BorderThickness="1" Text="{Binding WaybillNumber}" />
<Button Grid.Column="1" Content="*" Width="15" BorderThickness="1"/>
</Grid>
</Border>
use Grid instead of StackPanel. Setting fixed size (Width/Height) is not a good idea for adaptive layout. Grid will allow TextBox to stretch.
one option is to have separate columns for TextBox and Button:
<Border Grid.Row="4" Grid.Column="2" Margin="10,0,10,0"
BorderBrush="Gray" BorderThickness="1">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBox BorderBrush="LightGray" BorderThickness="1" Text="{Binding WaybillNumber}" />
<Button Content="*" Grid.Column="1" Width="15" BorderThickness="1"/>
</Grid>
</Border>
alternatively place them in the same cell and let Button overlap TextBox (it will look like as a part of TextBox but can hide part of a long text):
<Border Grid.Row="4" Grid.Column="2" Margin="10,0,10,0"
BorderBrush="Gray" BorderThickness="1">
<Grid>
<TextBox BorderBrush="LightGray" BorderThickness="1" Text="{Binding WaybillNumber}" />
<Button Content="*" HorizontalAlignment="Right" Margin="2" Width="15" BorderThickness="1"/>
</Grid>
</Border>

WrapPanel with 2 items WPF

I want to show a big text next to an image, in a resizable window.
I found here that it's pssible to use a WrapPanel, but this control need a fixed width and the width of my window is not fixe.
I tried the following code, but sometimes, the text is placed under the image (depanding on the window size) :
<Border Grid.Row="0" BorderBrush="Black" BorderThickness="1" CornerRadius="1" Background="PaleGoldenrod" Grid.Column="0" Margin="5">
<StackPanel Orientation="Vertical" Opacity="0.8" >
<WrapPanel Orientation="Horizontal" Width="{Binding ElementName=RadGridViewFoldersSettingsRSP, Path=Width}">
<Image Source="/Pics/Resources/btn_about_active.png" Margin="2" Width="20"/>
<TextBlock Text="blablabla" TextWrapping="WrapWithOverflow" Margin="2" FontStyle="Italic"/>
</WrapPanel>
</StackPanel>
</Border>
This border is above a grid as wide as the window.
Can you help me ?
To resolve my issue, i'm going to another way :
<Border Grid.Row="0" BorderBrush="Black" BorderThickness="1" CornerRadius="1" Background="PaleGoldenrod" Grid.Column="0" Margin="5">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image Source="/Pics/Resources/btn_about_active.png" Margin="2" Width="20" Grid.Column="0"/>
<TextBlock Grid.Column="1" Text="BIG TEXT" TextWrapping="WrapWithOverflow" Margin="2" FontStyle="Italic"/>
</Grid>
</Border>
Thanks to mm8 for his reactivity !

WPF Modal Window Transparency

I have created a modal WPF window that looks as follows:
Here is the code for the window:
<Window x:Class="Dionysus.Core.Controls.ModalWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ModalWindow" AllowsTransparency="True" Background="Transparent" WindowStyle="None">
<Grid Name="MainGrid">
<Rectangle Fill="Gray" Opacity="0.7" />
</Grid>
The "ErrorControl" is then added as follows:
MainGrid.Children.Add(uc);
The problem is as soon as I expand the stack trace, the controls transparency also changes:
I am assuming this has something to do with the ScrollViewer that uses the incorrect transparency, ie of the Rectangle instead of the containing Window.
I have also set the Opacity of the UserControl which owns the ScrollViewer to 1 and then binded the Opacity:
<ScrollViewer Background="WhiteSmoke" Opacity="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}, Path=Opacity}">
Can anyone help me?
--
UPDATE
Here is the code for the UserControl that is inserted into the Window
<Grid x:Name="LayoutRootx" Background="WhiteSmoke">
<StackPanel VerticalAlignment="Stretch">
<TextBlock TextWrapping="Wrap" Margin="5" Text="An error has occured:" Foreground="Black" FontSize="15" FontWeight="Medium"/>
<TextBlock TextWrapping="Wrap" Margin="5,10,5,5" Text="{Binding Error}"/>
<odc:OdcExpander Header="Stack Trace" Margin="5" IsExpanded="False" Background="WhiteSmoke">
<TextBox Text="{Binding StackTrace}" TextWrapping="Wrap" Margin="5,10,5,5" IsReadOnly="True" MaxHeight="370"/>
</odc:OdcExpander>
<odc:OdcExpander Header="Comment" Margin="5" IsExpanded="False">
<TextBox Text="{Binding Comment}" TextWrapping="Wrap" Margin="5,10,5,5" MaxHeight="370" Name="txtComment"/>
</odc:OdcExpander>
<StackPanel Margin="5,10,5,5" Orientation="Horizontal" HorizontalAlignment="Left">
<Button Style="{StaticResource DionysusButton}" Width="100" Height="23" IsDefault="True" Name="btnSendError">
<StackPanel Orientation="Horizontal">
<Image Source="/Dionysus.Shell;component/Images/camera-icon.png" Margin="0,0,5,0">
</Image>
<TextBlock Text="Send to IT" VerticalAlignment="Center"/>
<core:DionysusTriggerAction Height="0" Width="0" TargetControl="{Binding ElementName=btnSendError}" MethodName="SendError"></core:DionysusTriggerAction>
</StackPanel>
</Button>
<Button Style="{StaticResource DionysusButton}" Width="100" Height="23" Name="btnExit" Margin="10,0,0,0" IsCancel="True">
<StackPanel Orientation="Horizontal">
<Image Source="/Dionysus.Shell;component/Images/DeleteRed.png" Margin="0,0,5,0">
</Image>
<TextBlock Text="Close" VerticalAlignment="Center"/>
</StackPanel>
</Button>
<core:DionysusTriggerAction Height="0" Name="triggerAction2" Width="0" TargetControl="{Binding ElementName=btnExit}" MethodName="Exit"></core:DionysusTriggerAction>
</StackPanel>
</StackPanel>
</Grid>
If your window has a fixed size and cannot be resized, you can use the following trick:
<Grid>
<Border BorderThickness="100" BorderBrush="Gray" Opacity="0.7">
<Grid Background="White" Grid.Column="1" Grid.Row="1" x:Name="contentPlaceHolder">
<TextBlock Text="HELLO WORLD" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</Border>
</Grid>
However, it is unlikely that your Window will always have the same size, so to make it more dynamic, you could change the layout of the Window as follows:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="YourDesiredSize"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="YourDesiredSize"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Rectangle Fill="Gray" Opacity="0.7" Grid.Row="0" Grid.ColumnSpan="3"/>
<Rectangle Fill="Gray" Opacity="0.7" Grid.Row="2" Grid.ColumnSpan="3"/>
<Rectangle Fill="Gray" Opacity="0.7" Grid.Row="1" Grid.Column="0"/>
<Rectangle Fill="Gray" Opacity="0.7" Grid.Row="1" Grid.Column="2"/>
<Grid Grid.Column="1" Grid.Row="1" Background="White" x:Name="contentPlaceHolder">
<TextBlock Text="HELLO WORLD" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</Grid>
The result of this window placed on top of another looks more or less like this:
and then instead of adding to the MainGrid, add the UserControl to the contentPlaceHolder or however you want to call it:
contentPlaceHolder.Children.Add(uc);
Okay so I found a solution that works for me, I'm sure it's not the best but it might help someone having the same problem as I did.
The problem was that controls within my UserControl that I added to my Window were transparent, although I could not figure out the reason, I found a simple workaround.
By changing the OpacityMask property of the UserControl to whatever the required Background colour is, even if the controls opacity changes, it will be masked with the Brush that you supply.
uc.OpacityMask = Brushes.WhiteSmoke;
Hope it helps someone!

WPF Statusbar, stretch textblock to take as much space as possible

I created my own simple statusbarcontrol with 3 TextBlocks. Now I would like that the first Textblock takes as much space as it has available. That I don't seem to get done.. Now it only takes the space needed to display the text.
XAML:
<StatusBar Background="{StaticResource GradientBrush}">
<StatusBar.ItemsPanel>
<ItemsPanelTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
</Grid>
</ItemsPanelTemplate>
</StatusBar.ItemsPanel>
<StatusBarItem HorizontalAlignment="Left"
HorizontalContentAlignment="Right">
<Border BorderThickness="1"
BorderBrush="Black"
Padding="5 0 5 0"
Background="White">
<TextBlock Text="{Binding Message, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Foreground="{Binding TextColorMessage}"
Background="White"
/>
</Border>
</StatusBarItem>
<Separator Grid.Column="1" />
<StatusBarItem Grid.Column="2"
HorizontalAlignment="Right">
<TextBlock Text="{Binding Path=DatabaseName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</StatusBarItem>
<Separator Grid.Column="3" />
<StatusBarItem Grid.Column="4"
HorizontalAlignment="Right">
<TextBlock Text="{Binding Path=ComputerName}" />
</StatusBarItem>
Well this is pretty straight forward:
you had set the StatusBarItem HorizontalAlignment="Left" when it should be "strech", same for the HorizontalContentAlignment.
Also would suggest setting margin=0 on the border.
this is what i did so it will work for me:
<StatusBarItem HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch">
<Border BorderThickness="1"
BorderBrush="Black"
Margin="0"
Padding="5 0 5 0"
Background="White">
<TextBlock Text="{Binding Message, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Foreground="{Binding TextColorMessage}"
Background="White"/>
</Border>
</StatusBarItem>
if this is helpful please mark as answer
Try setting the StatusBarItem's HorizontalAlignment and HorizontalContentAlignment to Stretch.
Set the StatusBarItem's HorizontalContentAlignment to Stretch and the TextBlock's TextAlignment property to Right. (This second setting is only needed for the first StatusBarItem as it seems that you try to align the text to the right in it.)
StatusBar has only one HorizontalAlignment=Right item to effect, so you can get only the last item in wanted place. You can set statusBar's FlowDirection="RightToLeft" and add item in reversed order. Details: right placed items needn't StatusBarItem surrounded, but the left one need to be streched. Following code:
<StatusBar VerticalAlignment="Bottom" FlowDirection="RightToLeft"><!--flow right to left cause items right aligned-->
<!--make item's flow back left to right, avoid display disorder-->
<TextBlock x:Name="textBlock_status_R1" Text="111.147.168.20" Grid.Column="2" Margin="10,0" FlowDirection="LeftToRight"/>
<Separator/>
<TextBlock x:Name="textBlock_status_R2" Text="Working" Margin="10,0" FlowDirection="LeftToRight"/>
<Separator/>
<!--To fill rest space,need StatusBarItem packing and default HorizontalAlignment="Stretch"-->
<StatusBarItem FlowDirection="LeftToRight">
<TextBlock x:Name="textBlock_status_L1" Text="Information here."/>
</StatusBarItem>
</StatusBar>

Resources