I hope you can help me with my problem. It's about a custom designer for a WF 4.0 activity, but the problem is essentially in the WPF of the designer.
Some background
I've created a custom WorkFlow activity to send e-mails. For the custom designer for the activity, I've previously been using regular Textboxes for the "Subject" and "Body" of the e-mail, but I'd like to use the ExpressionTextBox to easily bind it to the InArguments of the activity. The ExpressionTextBoxes are in a grid, and this grid is on a StackPanel.
I've set the the MinWidth, MaxWidth and Margin of the ExpressionTextBoxes to fit with the other controls, and in the Visual Studio Designer (viewing the custom activity designer, not the actual WorkFlow) everything looks as it should.
<sapv:ExpressionTextBox Grid.Column="1" Grid.Row="2" Height="Auto" HorizontalAlignment="Right" Margin="4, 4, 4, 4"
Expression="{Binding Path=ModelItem.Subject, Mode=TwoWay, Converter={StaticResource ArgumentToExpressionConverter}, ConverterParameter=In}"
ExpressionType="{x:Type TypeName=sys:String}" OwnerActivity="{Binding Path=ModelItem}" VerticalAlignment="Center" MaxWidth="176" MinWidth="175" />
The problem
When used, initially it also looks as it should, but when the ExpressionTextBoxes are edited, they shrink into being really small. When text is entered, the control expands to fit the text, until it reaches its MaxWidth. When the editing ends, it goes back to it's MaxWidth. I'd prefer if it stayed the same size, regardless of being in edit-mode or not.
If you can't see it, open the image here
What I've tried
I've mostly been doing WinForms, and I'm pretty inexperienced with WPF, so I don't know if there are some funky properties or other settings that I've missed. I've tried setting width-properties of the parent controls (StackPanel and Grid), I've tried setting just the width (no min/max), but it seems to shrink regardless of what I set.
If you would like more information or code, please don't hesitate to ask.
Update
As you can see in the comments to Maurices answer, I figured out how to avoid the problem by removing the horizontalAlignment property, and then using margins to align it to the right. But I'm not going to mark an answer, until there's an explanation of why this behaviour happened in the first place. My XAML was almost identical to what Maurice posted, so there must be something wrong elsewhere.
The XAML for the ExpressionTextBox looks fine to me and when I try the following designer it works just fine.
<sap:ActivityDesigner x:Class="WorkflowConsoleApplication2.MyActivityDesigner"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:sap="clr-namespace:System.Activities.Presentation;assembly=System.Activities.Presentation"
xmlns:sapv="clr-namespace:System.Activities.Presentation.View;assembly=System.Activities.Presentation"
xmlns:sapc="clr-namespace:System.Activities.Presentation.Converters;assembly=System.Activities.Presentation">
<sap:ActivityDesigner.Resources>
<sapc:ArgumentToExpressionConverter x:Key="ArgumentToExpressionConverter" />
</sap:ActivityDesigner.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
</Grid.RowDefinitions>
<Label Content="Subject"
Grid.Row="2"
Grid.Column="0"/>
<sapv:ExpressionTextBox Grid.Column="1"
Grid.Row="2"
Height="Auto"
HorizontalAlignment="Right"
Margin="4, 4, 4, 4"
Expression="{Binding Path=ModelItem.Subject, Mode=TwoWay, Converter={StaticResource ArgumentToExpressionConverter}, ConverterParameter=In}"
ExpressionType="{x:Type TypeName=sys:String}"
OwnerActivity="{Binding Path=ModelItem}"
VerticalAlignment="Center"
MaxWidth="176"
MinWidth="175" />
</Grid>
</sap:ActivityDesigner>
So I suspect the problem is possibly in your grid definition.
Related
I'm reading a tutorial about c# wpf projects and at some point it tells me to put a tab control on my project and set its properties like this:
Grid.RowSpan="2" Canvas.Left="10" Canvas.Top="2" Width="408" Height="208" Grid.Row="1"
My novice problem is that I cannot find Grid.RowSpan property on properties panel in order to change it.
Are some properties available only from xaml editor?
Is there a way to find it on properties panel also?
You tabcontrol goes inside the page's grid, so the Grid.RowSpan property is inherited from that.
Additionally, you may have defined some rows in your grid in a way similar to this:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
So, basically, that should work. RowSpan is written with Capital "R" and "S" btw, could htat be it?
I'm not entirely sure, but some are definitely easier to use from XAML.
It is in the layout properties (see picture).
Grid.Rowspan in VS Properties
I am using the Ribbon control in WPF and I noticed there are 2 different versions.
using Microsoft.Windows.Controls.Ribbon;
If I use this one in my xaml and class, my whole window will be in a very old windows style.
using System.Windows.Controls.Ribbon;
If I use this one in my xaml and class, my Ribbontabs suddenly won't fill correctly anymore.
When I use both of them. With this:
<ribbon:RibbonWindow x:Class="WPSDashboard.Views.ShellWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ribbon="clr-namespace:System.Windows.Controls.Ribbon;assembly=System.Windows.Controls.Ribbon"
xmlns:r="clr-namespace:Microsoft.Windows.Controls.Ribbon;assembly=RibbonControlsLibrary"
xmlns:prism="clr-namespace:Microsoft.Practices.Prism.Regions;assembly=Microsoft.Practices.Prism"
Title="WPSDashboard"
x:Name="RibbonWindow"
Width="640" Height="480">
<Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- Ribbon Region -->
<r:Ribbon x:Name="Ribbon" prism:RegionManager.RegionName="RibbonRegion">
<r:Ribbon.ApplicationMenu>
<r:RibbonApplicationMenu SmallImageSource="Images\SmallIcon.png">
<r:RibbonApplicationMenuItem Header="Exit"
x:Name="MenuItemExit"
ImageSource="Images\Exit.png"
Command="{Binding ExitCommand}"/>
</r:RibbonApplicationMenu>
</r:Ribbon.ApplicationMenu>
</r:Ribbon>
<Grid x:Name="ClientArea" Grid.Row="1">
<!-- Workspace Region-->
<GridSplitter HorizontalAlignment="Left" Width="2" Grid.Column="1"/>
<ContentControl x:Name="WorkspaceRegion" Grid.Column="1" prism:RegionManager.RegionName="WorkspaceRegion" />
</Grid>
</Grid>
</ribbon:RibbonWindow>
My Ribbontabs will load but the window now looks like this:
I can't click on close and minimize and maximize. <---
How can I get the border to be normal instead of small?
I can't close my windows this way.
I found the best way to make it look and work good!
Instead of the tags <ribbon:RibbonWindow on the beginning of the xaml,
Make it <Window .
Also add this part:
xmlns:r="clr-namespace:System.Windows.Controls.Ribbon;assembly=System.Windows.Controls.Ribbon"
Then in your class delete your : RibbonWindow (If it's there)
If that doesn't work and you don't need the quick access toolbar, this may help:
Go back to your XAML, and change the Ribbon margin to -22 :
<r:Ribbon x:Name="Ribbon" prism:RegionManager.RegionName="RibbonRegion" Margin="0,-22,0,0" >
Now my application looks like this(with the -22 margin) :
Now it looks like a normal application without an ugly windows 98 or 2000 style and the close button, minizime button and maximize button are back!
I personally would, either play on margins, or better than that, investigate the style of that ribbon and change it the way it helps my needs
I have the problem, that my Grid is not filling the space as I want it.
Here some code:
<HubSection>
<Grid Width="850">
<Grid.RowDefinitions>
<RowDefinition Height="35"/>
<RowDefinition Height="*"/>
<RowDefinition Height="310"/>
</Grid.RowDefinitions>
<Input:RadDatePicker Grid.Row="0" Value="{Binding CurrentDate, Mode=TwoWay}" />
<ListView
Grid.Row="1">...
</ListView>
<Grid Height="310"
Grid.Row="2">...
</Grid>
...
I want that the middle row is filling the space up of the hubsection. Instead it now just fills up when the listview contains enough items.
Any idea?
Now the filled ListView:
I would try setting the VerticalContentAlignment of the HubSection to Stretch as well as setting the VCA of the outer grid to that option. I'm suspecting the default might be Center or Top and so the minimizing vertical alignment control from the parent control and the expanding star-sized row setting of the inner grid come in a little bit of a conflict that some layout prioritizing rules probably resolve in getting the VCA rule to win.
For similar layout issues it is usually best to analyze with a visual tree debugger such as the XAML Spy or WinRT XAML Toolkit. You can also try tracing these various properties by walking the visual tree with the VisualTreeHelper class yourself.
I need to add several user controls to a Canvas. The size of the UserControl depends on the number of items present in the ItemsControl of the UserControl. To position the controls properly and to draw interconnecting lines between the usercontrols, I need the absolute width/height w.r.t the parent canvas. How to get these? ActualHeight and ActualWidth are returning 0.
I had asked similar question earlier, but could not get the right answer.
EDIT: Adding XAML od UserControl
<UserControl x:Class="SilverlightApplication2.MyControl"
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"
DataContext="{Binding RelativeSource={RelativeSource Self}}" Loaded="UserControl_Loaded">
<Grid x:Name="LayoutRoot" Background="White">
<Border CornerRadius="3" BorderThickness="1" BorderBrush="LightGray">
<Grid Name="grid1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" >
<Grid.RowDefinitions>
<RowDefinition Height="40*" />
<RowDefinition Height="136*" />
</Grid.RowDefinitions>
...
<Grid Name="gridPC" Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition Height="55*" />
<RowDefinition Height="*" />
<RowDefinition Height="55*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
....
<ItemsControl x:Name="pitems" ItemsSource="{Binding RowsP}" Grid.Row="1">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Width="250" Orientation="Horizontal">
<TextBlock Text="{Binding X}" Width="100" />
<TextBlock Text="{Binding Y}" Width="130" />
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
......
</Grid>
</Grid>
</Border>
</Grid>
You have few options you can do this, forcing to call Window.Measure and Window.Arrange will make all values to be calculated, or you can get those values in the Window.Loaded event. This same issue is discussed already on this question.
If you are sizing to content:
window.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
window.Arrange(new Rect(0, 0, window.DesiredWidth, window.DesiredHeight));
If you are using an explicit window size:
window.Measure(new Size(Width, Height));
window.Arrange(new Rect(0, 0, window.DesiredWidth, window.DesiredHeight));
or
public MyWindow()
{
Loaded += delegate
{
// access ActualWidth and ActualHeight here
};
}
ActualWidth and ActualHeight work only after the control has been rendered.
To get the desired size of a control, you need to let it measure itself by calling it's Measure method. After that, you can use DesiredSize property which will contain the values you seek.
There is also a good article by Charles Petzold handling a similar situation:
Thinking Outside the Grid
I am actively creating a Silverlight timeline control and I don't do a measure as the previous posters advised. I simply wait for the final onsize call or other dependent properties OnChanged event.
Here is what I do to load my control which has a canvas:
Subscribe to the user control's Loaded event (which is the target for all dependent load events calls and on size event in (step #2)).
Subscribe to the Size Changed event (which calls the controls loaded event as mentioned in #1).
All dependent properties OnXXXPropertyChanged event call the OnLoad (#1).
Within the loaded event I check for this.ActualWidth to be set (non zero) along with whether all of my dependent properties are valid. (If they are all not set and also my boolean global flag states that it hasn't been loaded yet; it does nothing and exits (waiting a subsequent call).
Once my load event detects all dependent properties have been set and ActualWidth is not zero, it then begins the process of using the width and the dependent properties to begin to create my sub controls.
HTH
It has been a long time but I did something similar a few years ago. I don't recall all the details right now, I will look at this when I have more time this evening. I wanted to give you a quick idea of why you are getting 0 for the size.
This is primarily because the layout system in WPF occurs in two passes, the measure and the arrange pass. First the container control (in your case the Panel) asks it's children for their size once this pass is completed, the container will arrange it children using the sizes they calculated in the measure pass.
I would recommend reading the this MSDN article focusing on the Measuring and Arranging Children section. http://msdn.microsoft.com/en-us/library/ms745058.aspx
Let me know if this does not help, and I will spend some more time to refresh my memory on all the details.
Based on your edit you may want to check out this post describing how to create objects that are connected with lines. http://denisvuyka.wordpress.com/2007/10/21/wpf-diagramming-drawing-a-connection-line-between-two-elements-with-mouse/
I think this is more directed at your exact scenario.
I'm pretty new to WPF and C# and am trying to help out on some GUI stuff for work. We basically have 3 sections, a LHS (left hand side) [section 1], a RHS that has a top and bottom section [section 2 and section 3]. Looks like this
1 | 2
1 | -
1 | 3
They want a way to shrink each section with a button click. Currently the | and - are spacer items and can be dragged (Edit: this is done using a gridsplitter which they don't like). I did a little research and saw there are expander items and accordion items. I didn't know if either could be used for this scenario, and what would be the least hassle. In trying each just a bit, some additional questions for the controls come to mind since I'm not familiar with them.
Expander:
By shrinking section 1, would it make section 2 and 3 then take up the whole screen? Or can this only be done with an Accordion?
Is it hard/easy to change the <> icons to +- icons? If so, any tutorial out there?
Accordion:
Can the <> be changed to +-? If so, any tutorial out there?
Can the default color of blue be changed?
TIA
An Expander sounds like a suitable option for your situation. Fortunately it's included with WPF out of the box, unlike the Accordion control. But I found this question related to the Accordion control and thought it'd be useful for you to check out.
To change the appearance of the Expander toggle button you'll want to modify its control template. Changing the template to display plus or minus instead of arrows isn't too tough. If you visit the link you'll see you're going to want to change ExpanderToggleButton portion of the template.
Since you just want to change from using the arrows to using plus/minus signs you can simply change the Path data for collasped/expanded arrow. You can look here for more infortmation on drawing simple shapes with path.
Here is an example of someone modifying the control template of the Expander. It's for a different tweek in appearance, but it should be useful should you decide to go this route.
EDIT:
Really simple example (without the change in ToggleButton appearance) to get an idea of how to collaspe and save real estate:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColunmDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Expander Name="Section1" Grid.RowSpan="2" Grid.Colunm="0" ExpandDirection="Left">
<!-- Stuff goes here -->
</Expander>
<Expander Name="Section2" Grid.RowSpan="0" Grid.Colunm="1"
<!-- Stuff goes here -->
</Expander>
<Expander Name="Section3" Grid.RowSpan="1" Grid.Colunm="0"
<!-- Stuff goes here -->
</Expander>
</Grid>
You could use GridSplitter. The user can drag them to change the size. Not a click - a drag.
<GridSplitter Grid.Row="1" Grid.Column="1"
Width="3" Background="Purple" VerticalAlignment="Stretch" HorizontalAlignment="Center" ShowsPreview="False" >