Change Orientation of a WrapPanel in Wpf (mvvm) - c#

I got a problem with the design of my WPF program. My XAML looks like this:
<StackPanel Orientation="{Binding Orientation}">
<Border ... />
<Border ... />
<Border ... />
<Border Margin="2"
VerticalAlignment="Stretch"
CornerRadius="3"
Padding="4">
<WrapPanel>
<TextBlock VerticalAlignment="Center"
Text="Time Range:"
Width="66" />
<controls:WinFormsWrapper EndDateTime="{Binding EndDateTime,Mode=TwoWay}"
InitialEndDateTime="{Binding InitialEndDateTime}"
InitialStartDateTime="{Binding InitialStartDateTime}"
StartDateTime="{Binding StartDateTime,Mode=TwoWay}"/>
</WrapPanel>
</Border>
<Border ... />
</StackPanel>
Inside The WrapPanel you can see there is my WinFormsWrapper. In my Viewmodel i got a property Orientation which will determine how to Orientate the StackPanel. I want the WrapPanel now to fill the whole control horizontally if the Orientation is set to vertical and vice versa.
Does anyone know a good way to do this?
EDIT:
The Type of the property is System.Windows.Controls.Orientation and the possible values are: System.Windows.Controls.Orientation.Vertical and System.Windows.Controls.Orientation.Horizontal.

If you set a Background to your WrapPanel the panel is full size.
I think that you should use a DockPanel instead of your WrapPanel with the property value LastChildFill="True".
Your error comes from invalid values. Set a valid start value to your Orientation property
private Orientation orientation = Orientation.Horizontal;

Related

WPF How to make a Viewbox aware of its available space from within a StackPanel

I have a custom WPF control based on Soroosh Davaee’s ImageButton example at http://www.codeproject.com/Tips/773386/WPF-ImageButton. The custom control combines an Image and TextBlock in a horizontal StackPanel within a Button. (BTW, to get Soroosh’s example to run, I had to edit the solution properties so that “SampleView” is the startup project rather than “ExtendedButton” being the startup project.)
I want the text in the TextBlock to automatically shrink if necessary to avoid clipping at the right edge if the text is too long to fit naturally in the button. For example, if I edit Soroosh's MainWindow.xaml to make the button text too long to fit...
...
<EB:ImageButton Width="100" Height="30" Content="TextTooLongToFitInTheButton" Grid.Row="2"
...
<EB:ImageButton Width="100" Height="30" Content="TextTooLongToFitInTheButton" Grid.Row="2"
...
...the result is the following buttons with clipped text:
In researching this, it seems the simplest way to auto-shrink the content of a TextBlock is to wrap it within a Viewbox:
<Viewbox StretchDirection="DownOnly" Stretch="Fill">
<TextBlock ... />
</Viewbox>
DownOnly apparently prevents the Viewbox from enlarging the text to fill the space, and Fill (as opposed to Uniform) seems to tell it to stretch (shrink) only the dimension that needs to shrink (i.e. the horizontal dimension in my case).
In Soroosh's example Generic.xaml file, I wrapped the TextBlock in such a Viewbox:
<Button >
<StackPanel Orientation="Horizontal">
<Image Margin="2 0"
Source="{TemplateBinding Image}"
Width="{TemplateBinding ImageWidth}"
Height="{TemplateBinding ImageHeight}"
Visibility="{TemplateBinding Image,Converter={StaticResource VisibilityConvertor}}"
VerticalAlignment="Center"/>
I added--> <Viewbox StretchDirection="DownOnly" Stretch="Fill">
<TextBlock Text="{TemplateBinding Content}"
VerticalAlignment="Center"/>
I added--> </Viewbox>
</StackPanel>
</Button>
This produced exactly the same clipped button text. Just experimenting, I tried forcing the Viewbox to have a fixed width...
<Viewbox StretchDirection="DownOnly" Stretch="Fill" Width="60">
...which produced this:
...which shows the capability of the Viewbox, if only it could somehow know its available width when it's inside the StackPanel.
I did note that if I wrap the Viewbox around the whole StackPanel, it successfully auto-shrinks the entire content of the StackPanel:
<Button >
<Viewbox StretchDirection="DownOnly" Stretch="Fill" Width="60">
<StackPanel Orientation="Horizontal">
<Image Margin="2 0"
Source="{TemplateBinding Image}"
Width="{TemplateBinding ImageWidth}"
Height="{TemplateBinding ImageHeight}"
Visibility="{TemplateBinding Image,Converter={StaticResource VisibilityConvertor}}"
VerticalAlignment="Center"/>
<TextBlock Text="{TemplateBinding Content}"
VerticalAlignment="Center"/>
</StackPanel>
</Viewbox>
</Button>
...which produces very nearly what I want:
...but both the image and text are shrunk, and I want only the text shrunk.
How can I make the Viewbox, wrapping only the TextBox, know its available width (and height, I suppose) from within a cell of the StackPanel?
This is a common problem. The solution is simply to not use a StackPanel to do any kind of layout that requires re-sizing of child controls. It's simply not the correct Panel for the job. Instead, try using a Grid panel, which will resize its child controls. The StackPanel control is really only good for the most basic of layout duties... try anything more adventurous and you'll find yourself getting these issues.
One other alternative is to use the TextBlock.TextTrimming Property to trim the text instead... you could put the full text into a ToolTip too.

Two children to a border

I've created a border and inside it I put a combox. After that, I also added a checkbox but then VS complained that there's only one child property allowed. It's possible that I'm asking the wrong question.
Should I use a different control for "keeping stuff together"? Which one would that be?
If the border is correct for the purpose, what am I doing incorrectly, then?
<Border BorderBrush="Black" BorderThickness="1" ... >
<ComboBox x:Name="comboBox" ... />
<CheckBox x:Name="checkBox" ... />
</Border>
Border is a fine control to use if you want a border around your content, but its not a Panel, so it can only have one child. Simply do something like:
<Border BorderBrush="Black" BorderThickness="1" ... >
<StackPanel>
<ComboBox x:Name="comboBox" ... />
<CheckBox x:Name="checkBox" ... />
</StackPanel>
</Border>
Now the Border only has one child, and your other elements are laid out by a Panel element which can have multiple children.

Scalling the items in items Control

I am developing a control (Items control) to show boxes in a Room(for example sack).
If the room size is 10 *10 feet then I have to scale it to fit my Screen.
Also all the objects in the room will also need to be scaled.
In my view model I have a collection of these objects(i.e. boxes) with actual dimension.
The ItemPanel of my items control is like a canvas where I can freely move the objects.
currently in my Measure Override or Arrange override of the itemsPanel I get the height and width of the panel. With that height and width I apply the scaling to object while arranging.
So my question is, is the approach better or there is a better alternative.
Regards
Saurabh Dighade
Take a look at this code
<Grid x:Uid="Grid_1" Margin="10" ToolTip="{Binding ToolTip}">
<StackPanel x:Uid="StackPanel_1" Grid.Row="1" Orientation="Horizontal">
<Slider x:Uid="ScaleSlider" x:Name="ScaleSlider" Minimum="0.2" Maximum="5" LargeChange="0.05" SmallChange="0.01"
Value="{Binding ScaleSlider}" IsSnapToTickEnabled="True" TickFrequency="0.1" Visibility="Hidden"/>
</StackPanel>
<ScrollViewer x:Uid="ScrollViewer_1" Grid.Row="1" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Border x:Uid="AlStatusBorder" BorderBrush="#101010" BorderThickness="3"
Background="{Binding Color}"
x:Name="AlStatusBorder"
Padding="5"
CornerRadius="10" HorizontalAlignment="Center" VerticalAlignment="Top">
<Grid x:Uid="Grid_2">
<!-- Tachometer Gauge -->
<gauge:CircularGauge x:Uid="gauge:CircularGauge_1" Grid.Row="1" Grid.Column="2" FrameType="CircularTopGradient" Width="150" Height="150" Radius="75" Background="#444444"
RimBrush="#444444">
<gauge:CircularGauge.LayoutTransform >
<ScaleTransform x:Uid="ScaleTransform_1" ScaleX="{Binding ElementName=ScaleSlider, Path=Value}"
ScaleY="{Binding ElementName=ScaleSlider, Path=Value}"/>
</gauge:CircularGauge.LayoutTransform>
</gauge:CircularGauge>
</Grid>
</Border>
</ScrollViewer>
</Grid>
In grid_2 I implement my userControl. When I change a property ScaleSlider, element becomes bigger or smaller, and my usercontrol that is inside also changes it's sizes. May be it is what you are looking for. At least I can move this userControl; change sizes only by changing one property. Note that Im binding ScaleX and ScaleY values

Bing Maps Silverlight - Adding tooltips to pins generated in C#

I am attempting to convert a bing map implementation that uses standard PushPins in order to populate the map, but I need to add a tooltip to each pin. I found some options of how to do this on the website but the issue is I need the pushpins to be different from each other in a way that is dynamic. Based on the properties of each pin it must have a different background color.
The code already on this site all has the programmer use an image of the pushpin when they customize it.
So right now I need a way to either create a templated pushpin that is able to maintain the look and properties of a pushpin (so I can set background), while allowing a tooltip. Or instead having a regular pushpin have a tooltip or popup with it.
Any help would be appreciated!
Edited:
Control Template I am using
<ControlTemplate x:Key="NewPins" >
<Grid x:Name="pushPin" >
<Popup IsOpen="False" behaviors:RolloverPopup.HideDelay="0" behaviors:RolloverPopup.Target="{Binding ElementName=pushPin}" Margin="30,-20,0,0" >
<Border Background="White" BorderBrush="Black" CornerRadius="10" BorderThickness="1">
<StackPanel Orientation="Vertical" >
<TextBlock Text="{Binding Title}" Foreground="Black" FontWeight="Bold" TextWrapping="Wrap" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="10" />
<TextBlock Text="{Binding Content}" Foreground="Black" TextWrapping="Wrap" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="10" />
</StackPanel>
</Border>
</Popup>
</Grid>
</ControlTemplate>
This is setting up the pin in C#
Pushpin pin = new Pushpin()
{
Location = new Location( Double.Parse(item.PinLat), Double.Parse(item.PinLong)),
Content=String.Concat( GetNewlineString(item.LocationName), GetNewlineString(item.CallerName), GetNewlineString(item.PhoneNumber)),
Template=(ControlTemplate)Application.Current.Resources["NewPins"],
Width = 50,
Height = 65,
};
And this is creating the Bing Map
<c:BingMapAdSmart
AnimationLevel="UserInput"
Pins="{Binding DashboardViewModel.MapPins}"
NavigationVisibility="Visible"
SetViewZoomFactor="0"
MaxZoomLevel="7"
Visibility="{Binding NavViewModel.IsViewTransitioning, Converter={StaticResource TrueToCollapsedConverter}}" />
I may not really understand your question correctly, but i assume you need pushpins that are being created dynamically based on a template right? And you want to be able to change the tooltip (content property i assume) independently.
If thats the case, first you need to put a template resource to your resources in xaml;
<phone:PhoneApplicationPage.Resources>
<ControlTemplate x:Key="template_name" TargetType="m:Pushpin">
...this is your design part you can compile this xaml via Expression
</ControlTemplate>
</phone:PhoneApplicationPage.Resources>
then you'll need pass this value to every pushpin you've created dynamically codebehind. On this stage you can also set their content property, since they don't have a notification property, i don't know if you mean this but content property is the similar one. You can edit them like you edit other stuff;
myPushPin.template = (ControlTemplate)This.Resources["template_name"];
myPushPin.Content = "Hello World!";
This stage may differ according where you put your resources if its in phone:PhoneApplicationPage.Resources
if you put in Application.Resources
use this;
myPushPin.template = (ControlTemplate)Application.Current.Resources["template_name"];
myPushPin.Content = "Hello World!";
This should work, i don't have bing maps API or WP7 tools installed on this computer so i can't test it but this should be ok.
Happy coding!
Edit:
So if you want to change the background of a pushpin you don't have to hold back, it doesn't matter whether it has a control template or not. Actually every control has one as default. You can change the background as you always do
myPushpin.Background = new SolidColorBrush(Colors.Blue);
I have done exactly what you describe. The way i did this makes the most sense to me. Here is what I did:
I created a custom Pushpin (i.e. UserControl). This Xaml defines my custom pushpin. It assumes this pushpin is to be data-bound to. One of the binded properties is background Color. This will easily satisfy your dynamic color issue.
In the bing map control i defined the following:
The MyPushpinTemplate is defined in the UserControl.Resources like this:
MyPushpinControl is the UserControl.
I also have a data model class (that implements INotifyPropertyChanged). This class is bound to an instance of MyPushpinControl. this data model class has all the properties and is data-binded to the UserControl.
This is technically all you need to know.
To satisfy your tooltip issue, I simply added a tooltip to one of the panels within my custom pushpin. Simple as that.
Until I have a better solution I have decided the only thing I can think to do is to create a number of different pins to use. I don't need an infinite color solution so about 15 different pins should do the trick. Messy but it will work.
I just solved this issue to my complete satisfaction. To accomplish this, you need to have to create a Pushpin style with a key. Then inside this pushpin you create a standard pushpin (you can use another style on that but don't let it look back to this style, I used default), and a popup to go along with it. An example is below, I am using a local tool to do easy rollover popups, otherwise its standard stuff + bind maps.
<Style TargetType="bingMaps:Pushpin" x:Key="NewPins2">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="bingMaps:Pushpin" >
<Grid x:Name="pushPin" >
<Border Width="50" Height="65" >
<bingMaps:Pushpin Background="{TemplateBinding Background}" />
</Border>
<Popup IsOpen="False" behaviors:RolloverPopup.HideDelay="0" behaviors:RolloverPopup.Target="{Binding ElementName=pushPin}" Margin="30,-20,0,0" >
<Border Background="White" BorderBrush="Black" CornerRadius="10" BorderThickness="1">
<StackPanel Orientation="Vertical" >
<TextBlock Text="{Binding Title}" Foreground="Black" FontWeight="Bold" TextWrapping="Wrap" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="10" />
<TextBlock Text="{Binding Content}" Foreground="Black" TextWrapping="Wrap" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="10" />
</StackPanel>
</Border>
</Popup>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

WPF Create a slide out panel

I don't know how this works technically but my requirement is as follows. I have a DataGrid and to input data into the DataGrid, I want a panel at the bottom of the DataGrid that slides out on a button click showing input options. Except, as the panel slides out, the DataGrid has to resize vertically as well. Can someone throw some light on how I can implement this?
You should be able to use a StackPanel with 2 children, your grid and your panel. Set the initial height of your panel to 0. Once the button is clicked, set the height to whatever you need it to be (e.g., MyPanel.Height = 20). You might want to wrap the grid in a ScrollViewer in case that is needed.
<StackPanel Orientation="Vertical">
<ScrollViewer Height="Auto" VerticalAlignment="Stretch">
<Grid Height="*" VerticalAlignment="Stretch" />
</ScrollViewer>
<ContentControl x:Name="MyPanel" Height="0" />
</StackPanel>
You might need to experiment with VerticalAlignment and Height="Auto" or Height="0" to get the layout you want.
You can use Expander. Please look at the following code snippet.
<DockPanel>
<Expander DockPanel.Dock="Bottom">
<StackPanel>
<TextBlock Height="25"></TextBlock>
<TextBlock Height="25"></TextBlock>
<TextBlock Height="25"></TextBlock>
</StackPanel>
</Expander>
<Border BorderBrush="LightGreen" BorderThickness="2">
<DataGrid/>
</Border>
</DockPanel >

Categories