I have a simple page with a rectangle, an ellipse, two sliders and a textblock.
The two slider controls (via binding) the height and width of the rectangle.
I would like to set the width and height of the ellipse based on the smallest value of the rectangles dimensions. The XAML code looks like this:
<UserControl
x:Class="App16.MyUserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App16"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="400"
d:DesignWidth="400"
x:Name="MyRoot">
<Grid Background="Black">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="2*" />
<RowDefinition />
</Grid.RowDefinitions>
<Rectangle Name="rect" Fill="Yellow"
Width="{Binding ElementName=rectX,Path=Value}"
Height="{Binding ElementName=rectY,Path=Value}" Grid.Column="0"/>
<Ellipse Fill="Yellow"
Width="{Binding ElementName=MyRoot,Path=SampleFunction}"
Height="{Binding ElementName=MyRoot,Path=SampleFunction}" Grid.Column="1" />
<StackPanel Grid.Row="1" Grid.ColumnSpan="2">
<Slider Name="rectX" HorizontalAlignment="Stretch" Minimum="100" Maximum="200" Value="150" />
<Slider Name="rectY" HorizontalAlignment="Stretch" Minimum="100" Maximum="200" Value="150" />
<TextBlock Foreground="White" Text="{Binding ElementName=MyRoot, Path=SampleFunction}" />
</StackPanel>
</Grid>
The code behind looks like this:
public Double SampleFunction {
get { return (rect.Width <= rect.Height ? rect.Width : rect.Height); }
}
In its current state, the rectangle resizes properly according to the value in the sliders, but "SampleFunction" is never called after the page is loaded.
Of course I could do this with the "RESIZED" event, but I wondering if this was possible without doing that.
Any suggestions? When the user adjust the slider control I would like to see the rectangle and ellipse change size.
Thanks!
Henk's suggestion with my comment would make it work, but actually for your scenario you can remove the bindings altogether and simply set
<Ellipse
Fill="Yellow"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
Stretch="Uniform" />
Your SampleFunctionneeds to be renamed (it's a property, not a function).
And to make it work for DataBinding it needs to implement INotifyPropertyChanged
In addition, the internal logic should probably be base on ActualWidth and ActualHeight.
Related
I'm working on a windows phone 8.1 project.
I'm trying to perform an animation of my grid.
Let's see the code first.
<Page
x:Class="CityBoxApp.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:CityBoxApp"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid Background="#353C3F">
<Grid.RowDefinitions>
<RowDefinition Height="20*"/>
<RowDefinition Height="80*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<TextBlock Text="Test" HorizontalAlignment="Center" VerticalAlignment="Center"
FontSize="35" FontStyle="Italic"/>
<Grid Height="15"
VerticalAlignment="Bottom"
Background="#EC641A"/>
</Grid>
<Grid Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center">
<Border BorderBrush="Snow" BorderThickness="3" Padding="20, 40, 20, 40">
<StackPanel>
<Button Width="280" Content="Search around me" Margin="0, 0, 0 ,25"/>
<Button Width="280" Content="Search with an address"/>
</StackPanel>
</Border>
</Grid>
</Grid>
</Page>
I've been looking at lots of stuff on google but basically the problem is that the main grid always has a size in those cases. What i'm trying to perform is basically to translate my grid (Grid.Row 1) from outside of the screen from the right to the middle of the screen like it is now. What i would like it to be able to do something that would fit any size of screen. Any advice/example or documentation on this precise subject ?
Thank you guys a lot!
I have built a WPF application with a variable width and height (xaml height and width definition for the window is set to Auto). Once the contents of the window are loaded, the width does not (well, is not supposed to) change. The height might change as items are removed or added from the list.
The background is a gradient, not an image.
After a period where the application is idling and isn't the top-most, when switching back to the application, the window is wider as a black bar was added, extending the window to the right.
.
(Before this black bar appears, the window's width is the section with the blue gradient background)
I've added a hidden menu item to the window and when the user presses Alt the menu appears. At first, I simply added the menu and opening it caused the window to re-render as menu the item suddenly became visible and added to the window's height. As the window was re-rendered, the black bar disappeared and the window was its original width.
I tried the following solutions by adding an event where Window.OnFocus calls a function which:
changes the width (adds 1 pixel and then removes 1 pixel)... but this doesn't seem to do anything.
checks the width of the window. If the width is larger than the expected width, a re-render is manually called. But no dice...
What is causing this black bar to appear? How can I prevent it from happening?
The biggest problem here is that I can't seem to consistently reproduce the problem... sometimes, the application will sit open, idling in the background for the whole day and this won't happen. Sometimes, I'll go out to lunch, come back and there it is...
The content is loaded dynamically upon starting up, and there's a webservice call initiated every few minutes to check for changes. At this stage of development and testing, there aren't all that many changes happening so that the ui items are simply static most of the time. Even so, this black bar will appear at times after the application idles for a while, as mentioned.
Per suggestion, here is the xaml for the application:
MainWindow:
<Window x:Class="MyApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:y="clr-namespace:MyApp"
Title="MyApp"
Height="Auto" Width="390"
SizeToContent="WidthAndHeight"
WindowStyle="SingleBorderWindow"
WindowStartupLocation="Manual"
ResizeMode="CanMinimize">
<Grid Name="MainGrid" Style="{StaticResource Normal}">
<Grid.RowDefinitions>
<RowDefinition Height="18" />
<RowDefinition Height="65"/>
<RowDefinition Height="Auto" MinHeight="200"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150" />
<ColumnDefinition Width="218" />
</Grid.ColumnDefinitions>
<Menu Grid.ColumnSpan="2"
[SETTINGS REMOVED FOR BREVITY]>
</Menu>
[ELEMENTS REMOVED FOR BREVITY]
<Grid Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" Height="Auto" Width="Auto" x:Name="ContentGrid"></Grid>
</Grid>
</Window>
MainPanel (which goes into the ContentGrid):
<UserControl x:Class="MyApp.MainPanel"
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"
Height="Auto" Width="Auto" FlowDirection="RightToLeft">
<Grid Margin="19,0,19,0">
<Grid.RowDefinitions>
<RowDefinition Height="65" />
<RowDefinition Height="Auto"/>
<RowDefinition Height="75" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="160" />
<ColumnDefinition Width="85" />
<ColumnDefinition Width="85" />
</Grid.ColumnDefinitions>
<TextBlock Name="FirstHeader" Grid.Column="0" Grid.Row="0" Style="{StaticResource Header}" Text="***" />
<TextBlock Name="SecondHeader" Grid.Column="1" Grid.Row="0" Style="{StaticResource Header}">***<LineBreak />***</TextBlock>
<TextBlock Name="ThirdHeader" Grid.Column="2" Grid.Row="0" Style="{StaticResource Header}" Text="***" />
<StackPanel Name="MainStack" Grid.Row="1" Grid.ColumnSpan="3" />
<Button Name="ActionButton" Grid.ColumnSpan="3" Grid.Row="2" FlowDirection="LeftToRight" Style="{StaticResource NotInService}" Click="ActionButton_Click" />
</Grid>
</UserControl>
And the MainStack in the MainPanel is filled with these:
<UserControl x:Class="MyApp.mItem"
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="35" d:DesignWidth="348" FlowDirection="RightToLeft">
<Grid Margin="0,0,0,05">
<Grid.RowDefinitions>
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="160" />
<ColumnDefinition Width="85" />
<ColumnDefinition Width="85" />
</Grid.ColumnDefinitions>
<Button Grid.Row="0" Grid.Column="0" Name="PanelActionButton" Style="{StaticResource PanelActionButton}" Click="PanelActionButton_Click">
<TextBlock Name="AnswerButtonText" Style="{StaticResource ButtonText}"></TextBlock>
</Button>
<Label Grid.Row="0" Grid.Column="1" Name="SecondCol" Style="{StaticResource SecondCol}" />
<Label Grid.Row="0" Grid.Column="2" Name="ThirdCol" Style="{StaticResource ThirdCol}" />
</Grid>
</UserControl>
I don't know if it's pertinent, but this is the way I've styled the background:
<Style TargetType="{x:Type Grid}" x:Key="Normal">
<Setter Property="Background">
<Setter.Value>
<RadialGradientBrush GradientOrigin="0.5,0.5" Center="0.5,0.5" RadiusX="1" RadiusY="1">
<RadialGradientBrush.GradientStops>
<GradientStop Color="#00AEEF" Offset="0" />
<GradientStop Color="#034ea2" Offset="1" />
</RadialGradientBrush.GradientStops>
</RadialGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="FlowDirection" Value="RightToLeft" />
</Style>
Some suggestions:
SizeToContent="WidthAndHeight"
could be changed to
SizeToContent="Height"
since you also defined the width to be 390.
Besides that, check if the window with the black area is still the expected width of 390.
Although it´s not in your posted code, check if elements could extend the width with it´s content (like images, long strings, etc.).
Another thing you should consider is to carefully choose your margins and widths (and heights) since they could easily sum up.
E.g. your using
<Grid.ColumnDefinitions>
<ColumnDefinition Width="160" />
<ColumnDefinition Width="85" />
<ColumnDefinition Width="85" />
</Grid.ColumnDefinitions>
twice and inside grids which each have a margin.
Also have a look at the menu you´re using. Since it´s using some visibility converter, my guess is, that it might generate a menu that could be more than 390 wide.
And finally... what´s with the
FlowDirection="RightToLeft"
If there´s no real need for it, delete it :)
I'm struggling with a layout problem. My usercontrol contains a border, with a canvas as a child.
This canvas contains a grid, and that grid contains 2 canvas (1 column and 2 rows with different colors).
My problem is that the grid overlaps the border on his right side, and I don't know why. I tried to set the ClipToBounds property of my main canvas to "True", but with no effect.
Can you help me ?
Here is the problem :
And here is the code :
<Border Name="MainBorder" BorderBrush="Black" BorderThickness="1">
<Canvas Name="MainCanvas" Height="30" ClipToBounds="True">
<Grid Width="{Binding ElementName=MainCanvas, Path=ActualWidth}">
<Grid.RowDefinitions>
<RowDefinition Height="5" />
<RowDefinition Height="5" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Canvas Name="CanvasTop" Grid.Row="1" Grid.Column="0" Background="Beige" />
<Canvas Name="CanvasBottom" Grid.Row="0" Grid.Column="0" Background="LightGray" />
</Grid>
</Canvas>
</Border>
Thank you for your help.
I think it is your Width="{Binding ElementName=MainCanvas, Path=ActualWidth}" line which is causing that.
Instead of the width property can you try HorizontalAlignment="Stretch" ?? this will make sure that it uses the whole width
Problem solved, there was a function in the code-behind that resized the control the wrong way :
public void SetMainCanvasWidth(double size)
{
Width = Math.Max(2, size); // that line was evil. removed it and it runs
MainCanvas.Width = Math.Max(2, size);
}
Thank you for your help.
Below is my xaml code :
<Window x:Class="ScoresBank.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow">
<DockPanel LastChildFill="True">
<WrapPanel DockPanel.Dock="Top">
<ToolBar Height="25"></ToolBar>
</WrapPanel>
<WrapPanel DockPanel.Dock="Bottom">
<StatusBar Name="stbBottom" Height="25"
BorderThickness="2"
BorderBrush="Black">Example</StatusBar>
</WrapPanel>
<StackPanel DockPanel.Dock="Left">
<DockPanel LastChildFill="True">
<WrapPanel DockPanel.Dock="Top">
<Button Name="btnBrowseTags">TAGS</Button>
<Button Name="btnBrowseTitles">TITLES</Button>
</WrapPanel>
<ComboBox DockPanel.Dock="Top" Name="cbxCategory">
Example
</ComboBox>
<WrapPanel DockPanel.Dock="Bottom">
<TextBox Name="txtKeyword"></TextBox>
<Button Name="btnFind">Find</Button>
</WrapPanel>
<ListBox Name="lbxBrowse">
</ListBox>
</DockPanel>
</StackPanel>
<StackPanel DockPanel.Dock="Right">
<Button>Example</Button>
</StackPanel>
<Canvas>
</Canvas>
</DockPanel>
And this is my current layout view :
So, what I mean with filling the container are :
Making lbxBrowse to fill the mid-space of the DockPanel inside the left StackPanel.
Making txtKeyword to fill the WrapPanel.
Making stbBottom to fill the WrapPanel.
What I've tried :
It seems i've put them in a DockPanel with LastChildFill="True". But it seems doesn't work.
I don't know about this, since it's not possible to put it into a DockPanel first.
I don't know anything about this.
I don't use fixed size, since I need them to keep neat even when resized in multiple screen resolution. The fixed size on ToolBar and StatusBar seems required, otherwise, the text will be unseen.
P.S. If possible, I prefer the solution to be XAML code, rather than the C# code. Otherwise, C# code is fine too.
Thank you.
You should use a Grid. It is more easier to configure. Here is an example (I don't know exactly how you want to setup your layout).
<Window x:Class="SampleWpf.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="400" Width="600">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button Margin="5" Content="TAGS"
Grid.Column="0" Grid.Row="0" />
<Button Margin="5" Content="TITLES"
Grid.Column="1" Grid.Row="0" />
<Button Margin="5" Content="EXAMPLES"
Grid.Column="2" Grid.Row="0"
HorizontalAlignment="Right"/>
<ComboBox Margin="5"
Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="1" />
<ListBox Margin="5"
Grid.Column="2" Grid.Row="1" Grid.RowSpan="2" />
<Button Margin="5" Content="EXAMPLE"
Grid.Column="2" Grid.Row="3" HorizontalAlignment="Left" />
</Grid>
</Window>
And the result:
With a grid you can set the height and the width of the columns and rows to a specific value (in points, pixels, cm, etc.), to column content (Auto) or proportional to the grid (with *).
Instead of using a StackPanel and DockPanel you can use Grid and set Grid.ColumnDefinitions and Grid.RowDefinitions. You can specify directly each row Height and each column Width. It's easier to use and it automaticly fit to content and container.
I'm trying to ditch Windows Forms, and learn to use WPF professionally from now on. Pictured above is a form done in Windows Forms that I'd like to recreate in WPF.
Here is the XAML I have so far:
<Window x:Class="PizzaSoftware.UI.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="297" Width="466" >
<Grid ShowGridLines="True">
<Grid.ColumnDefinitions>
<ColumnDefinition Width=".20*"/>
<ColumnDefinition />
<ColumnDefinition Width=".20*"/>
</Grid.ColumnDefinitions>
<Rectangle Grid.Column="0">
<Backcolor?
</Rectangle>
</Grid>
</Window>
Is this even the right approach, I mean using a Rectangle. In my Windows Forms example, I used a Panel and gave it a .BackColor property.
What's the WPF way to achieve this?
Thank you.
Yes, your approach is just fine. Set the background color with the Fill property:
<Rectangle Grid.Column="0" Fill="Orange" />
<Rectangle Grid.Column="2" Fill="Orange" />
<Rectangle Grid.Column="0"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
Fill="Orange" />
Set the background of the window to your orange color. Then set the background of the grid to white, set the width of the grid so that it leaves space on either side, and set the grids HorizontalAlignment to center.
<Windows ....
Background="Orange>
<Grid Background="White" HorizontalAlignment="Center" Width="300">
...
</Grid>
</Window>
I'd skip the rectangle and set the background color on the grid itself, then set colors on components within to grid.
<Grid Background="Orange">
You can set the Background property of your grid to Orange and then add your control in the middle column and Set its Background property to White. Here is a sample code:
<Window x:Class="PizzaSoftware.UI.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="297" Width="466"
Height="297"
Width="466">
<Grid ShowGridLines="True" Background="Orange">
<Grid.ColumnDefinitions>
<ColumnDefinition Width=".20*"/>
<ColumnDefinition />
<ColumnDefinition Width=".20*" />
</Grid.ColumnDefinitions>
<!--Control with white background in second column-->
<GroupBox Background="White" Grid.Column="1">
<!-- Groupbox content here-->
</GroupBox>
</Grid>
</Window>