So, my problem is that i'm trying to move some usercontrols around in a canvas.
This actually works very well, as long as the mousepointer is inside the dockpanel, which is what the usercontrol is made of. However, inside the dockpanel, there are several itemscontrols, and if I click on those, and try to move it, an exception is generated, stating something like "Unable to cast object of type "System.String" to type "UMLDesigner.Model.Node".
This makes sense, but is there a way to get the DockPanel, instead of the Itemscontrol, even though it is the itemscontrol that is clicked?
There is the relevant C# code:
public void MouseMoveNode(MouseEventArgs e)
{
//Is the mouse captured?
if (Mouse.Captured != null)
{
FrameworkElement movingClass = (FrameworkElement)e.MouseDevice.Target;
Node movingNode = (Node)movingClass.DataContext;
Canvas canvas = FindParent<Canvas>(movingClass);
Point mousePosition = Mouse.GetPosition(canvas);
if (moveNodePoint == default(Point)) moveNodePoint = mousePosition;
movingNode.X = (int)mousePosition.X;
movingNode.Y = (int)mousePosition.Y;
}
}
public void MouseUpNode(MouseEventArgs e)
{
//Used to move node
FrameworkElement movingClass = (FrameworkElement)e.MouseDevice.Target;
Node movingNode = (Node)movingClass.DataContext;
Canvas canvas = FindParent<Canvas>(movingClass);
Point mousePosition = Mouse.GetPosition(canvas);
new MoveNodeCommand(movingNode, (int)mousePosition.X, (int)mousePosition.Y, (int)moveNodePoint.X, (int)moveNodePoint.Y);
moveNodePoint = new Point();
e.MouseDevice.Target.ReleaseMouseCapture();
}
And the xaml for some of the usercontrol:
<DockPanel.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0.0">
<LinearGradientBrush.GradientStops>
<GradientStop Color="Azure" Offset="0"/>
<GradientStop Color="Transparent" Offset="1"/>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</DockPanel.Background>
<TextBox Text="{Binding ClassName}" HorizontalAlignment="Center" DockPanel.Dock="Top" Margin="5,0,5,0"/>
<!--Note the " : " is acutally being written to the GUI-->
<ItemsControl Name="attributeList" ItemsSource="{Binding Attributes}" Margin="5,0,5,0" DockPanel.Dock="Top">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock><Run Text="{Binding Path=.}"/> : <Run Text="Type her"/></TextBlock>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<ItemsControl Name="propertiesList" ItemsSource="{Binding Properties}" Margin="5,0,5,0" DockPanel.Dock="Top">
</ItemsControl>
<ItemsControl Name="methodsList" ItemsSource="{Binding Methods}" Margin="5,0,5,0" DockPanel.Dock="Top">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock><Run Text="{Binding Path=.}"/>() : <Run Text="Type her"/></TextBlock>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DockPanel>
I would of course also like to know if there is a smarter or better way of doing this.
Add IsHitTestVisible="False" to ItemsControl.
Related
I'm fairly new at coding and i'm struggling with a popup that doesn't appear at runtime.
I'm trying to make an autocomplete/suggestion popup list but i can't seem to be able to make it work.
Here's my XAML:
<Grid Grid.Row="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="130"/>
<ColumnDefinition x:Name="editorInputColumn"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Ajouter (séparateur ';') :">
<TextBlock.Foreground>
<SolidColorBrush Color="{DynamicResource FontColor}"/>
</TextBlock.Foreground>
</TextBlock>
<Grid x:Name="popupEditorGrid" Grid.Column="1" Visibility="Visible">
<Popup Placement="Top" Visibility="Visible" StaysOpen="True" Panel.ZIndex="1000" x:Name="EditorPopup" Grid.Column="1" Width="{Binding Path=ActualWidth, ElementName=editorInputColumn}">
<StackPanel x:Name="EditorPopupStackPanel">
<StackPanel.Background>
<SolidColorBrush Color="{DynamicResource EllipseSecondary}"/>
</StackPanel.Background>
<TextBlock Text="test"/><!--this is just an attempt at displaying something in the popup, but even this does not appear at runtime-->
</StackPanel>
</Popup>
</Grid>
<TextBox Grid.Column="1" KeyUp="editorAddInput_KeyUp" x:Name="editorAddInput" >
<TextBox.BorderBrush>
<SolidColorBrush Color="{DynamicResource BoutonMarge}"/>
</TextBox.BorderBrush>
</TextBox>
</Grid>
and here's the code behind:
private void editorAddInput_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
{
string lastInput;
List<string> inputList = editorAddInput.Text.ToUpper().Split(',', ';').ToList();
if (inputList.Count != 0)
{
lastInput = inputList[inputList.Count - 1];
}
else
{
lastInput = editorAddInput.Text;
}
List<Editor> matchingEditorsList = new List<Editor>();
EditorPopupStackPanel.Children.Clear();
foreach(Editor editor in localEditorsList)//look up among all known names
{
if(editor.Name.StartsWith(lastInput))
{
matchingEditorsList.Add(editor);
}
}
if(matchingEditorsList.Count!=0)
{
EditorPopup.Visibility = Visibility.Visible;
foreach(Editor editor in matchingEditorsList)
{
EditorPopupStackPanel.Children.Add(new TextBlock() { Text = editor.Name });
}
EditorPopup.StaysOpen = true;
EditorPopup.IsOpen = true;
}
else
{
EditorPopup.Visibility = Visibility.Collapsed;
EditorPopup.IsOpen = false;
}
}
The input Textbox is supposed to be able to get several names, separated by a ";", so I start by getting the last one being typed.
Funny enough, the popup does appear in Visual Studio's Conceptor view when selected, but not when running. I've tried playing with z-index with no success. Any idea on what i messed up?
Put textbox inside grid in XAML
You are missing the IsOpen property, which should be set to true for the popup to be displayed.
From trial and error I managed to highlight part of text in a textblock which is in a datatemplate of a listbox bounded to a property of a custom class. But the problem now is that when highlighting the text i get a weird unknown space between the highlighted text and the rest of the text.
Here is part of the XAML
<Grid x:Name="LayoutRoot" Background="White">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBox Name="textBox1" TextChanged="textBox1_TextChanged"/>
<ListBox Grid.Row="1" Name="listBox1">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Name="gridOfListbox" Height="25" Margin="0,2">
<DockPanel Name="dockpanelWithTxtBlock">
<TextBlock Name="textbloxk" DockPanel.Dock="Left" FontSize="15" TextAlignment="Center">
<Run Background="Yellow" Text=""></Run>
<Run Text="{Binding ProductID}"></Run>
</TextBlock>
</DockPanel>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
And here part of the code used
ObservableCollection<TItem> items = new ObservableCollection<TItem>();
TItem[] source = new TItem[] { new TItem("Hello"), new TItem("World"), new TItem("System"), new TItem("SystemDefault"), new TItem("SystemFolder") };
And the method for event changedtext
private void textBox1_TextChanged(object sender, TextChangedEventArgs e)
{
string match = textBox1.Text;
foreach (TItem TItem in listBox1.Items)
{
ListBoxItem lbi = (ListBoxItem)this.listBox1.ItemContainerGenerator.ContainerFromItem(TItem);
TextBlock txtBlck = FindFirstElementInVisualTree<TextBlock>(lbi);
Run bold = (Run)txtBlck.Inlines.FirstInline;
Run normal = (Run)txtBlck.Inlines.LastInline;
string s = bold.Text + normal.Text;
if (s.ToLower().StartsWith(match.ToLower()))
{
bold.Text = s.Substring(0, match.Length);
normal.Text = s.Substring(match.Length);
}
else
{
bold.Text = "";
normal.Text = s;
}
}
}
FindFirstElementInVisualTree method is used to find the textboxes needed to search of.
If anymore code is needed let me know.
I also added an image to demonstrate what the problem is.
An help will be appreciated!
Link for image: http://i.stack.imgur.com/rOj0m.png
When you use Run within a TextBlock in XAML, everything not wrapped in <> are considered actual strings. Having a line break would mean a space. Put the two Runs within the same line (without a space in between too).
<TextBlock Name="textbloxk" DockPanel.Dock="Left" FontSize="15" TextAlignment="Center">
<Run Background="Yellow" Text="" /><Run Text="{Binding ProductID}" />
</TextBlock>
Edit
By the way, I just saw your first question which was marked as duplicate. This question is asked correctly; so you should ask questions in this manner in the future.
<maps:Map x:Name="map">
<maptk:MapExtensions.Children>
<maptk:MapItemsControl Name="pushpinItems">
<maptk:MapItemsControl.ItemTemplate>
<DataTemplate>
<maptk:Pushpin GeoCoordinate="{Binding geoCoordinateLocation}" Content="{Binding name}" PositionOrigin="0.5,0.5"/>
</DataTemplate>
</maptk:MapItemsControl.ItemTemplate>
</maptk:MapItemsControl>
</maptk:MapExtensions.Children>
</maps:Map>
...
ObservableCollection<PinItem> pinsCollection = new ObservableCollection<PinItem>();
private async void updateMap()
{
WebApiWorker webApi = new WebApiWorker();
var responce = await webApi.GetAllPins();
this.pinsCollection.Clear();
foreach (PinItem pin in responce.array)
{
this.pinsCollection.Add(busActivity.MonitoredVehicleJourney);
}
}
I call my updateMap() method every 5 sec to get the updated pin locations from web service. When the pushpins are updated, they jump like 5 mm on screen.
If i set pushpin PositionOrigin="0,0" then pins are not jumping/flickering any more but they are little sifted as I have ellipse pushpins.
Any ideas how to fix this?
I've used custom ControlTemplate to resolve this issue:
<ControlTemplate TargetType="toolkit:Pushpin" x:Key="PinTemplate">
<Grid x:Name="ContentGrid" FlowDirection="LeftToRight" Margin="0,-60,0,0">
<StackPanel Orientation="Vertical">
<Grid Background="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Background}"
HorizontalAlignment="Left"
MinHeight="31"
MinWidth="29">
<ContentPresenter x:Name="Presenter"
Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content}"
FlowDirection="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=FlowDirection}"
Margin="4" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</Grid>
<Polygon Fill="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Background}"
Points="0,0 29,0 0,29"
Width="29"
Height="29"
Margin="0,-1,0,0"
HorizontalAlignment="Left"/>
</StackPanel>
</Grid>
</ControlTemplate>
Then I've created Pushpins from my code like this:
var pp = new Pushpin
{
Background = cObject.Bcolor,
GeoCoordinate = cObject.Coordinate,
Content = ppIc.Convert(cObject.Name, typeof (BitmapImage), null, CultureInfo.CurrentUICulture),
DataContext = cObject,
Template = this.Resources["PinTemplate"] as ControlTemplate
};
pp.Tap += UIElement_OnTap;
var overlay = new MapOverlay
{
Content = pp,
GeoCoordinate = pp.GeoCoordinate
};
_pushpinLayer.Add(overlay);
The key here is to set a proper margin on root-level Grid of pushpin's template so it moves all elements higher and you don't have to set PositionOrigin="0,1".
I've found some workaround on 3d party site:
I found a Workaround. Before I clear the PushPin-Collection - which leads to those jumping PushPins - I create a Bitmap of the Map and Show it above the map. Once the collection is updated I again hide the Bitmap-Map. This works for the Moment, but takes more resources than necessary:
System.Windows.Media.Imaging.WriteableBitmap bmp = new System.Windows.Media.Imaging.WriteableBitmap((int)_map.ActualWidth,(int)_map.ActualHeight);
bmp.Render(_map, new System.Windows.Media.TranslateTransform());
bmp.Invalidate();
MapImage = bmp;
MapImageVisibility = Visibility.Visible;
But it looks not good enough :(
What I am trying to do is to create some sort of "rooms"(like a chat group, a sharing center or whatever you want). All the room are created the same way, but each one of them contains different informations. Each of these rooms is contained in a TabItem. I managed to create dynamically all the Tabitems, to give those a Grid and a Canvas. But at the moment I am facing a problem: I created a ControlTemplate Called RoomMenu that will show different buttons and, the most important, the people connected in this room in a ListBox(I retrieve those people from a WebService each time I change the selected Tabitem). But since my ListBox is in a ControlTemplate I have no idea how to access the ListBox ItemSource to bind a generic List to it. Down Below is the code used to create my rooms and their content.
Here is my room menu class:
public class RoomMenu : ContentControl
{
public RoomMenu()
{
DefaultStyleKey = typeof(RoomMenu);
}
public string Current_room_id;
public string FullName;
public string Rights;
}
And here is the ControlTemplate located in generic.xaml:
<Style TargetType="test:RoomMenu">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="test:RoomMenu">
<Grid x:Name="MenuGrid">
<Border HorizontalAlignment="Stretch" VerticalAlignment="Stretch" BorderBrush="Black" CornerRadius="2" Background="Black">
<StackPanel Orientation="Vertical">
<Border x:Name="Room_friend_border" Background="Gray" CornerRadius="4" Margin="5">
<ListBox x:Name="current_room_friends" ItemsSource="{Binding ''}" Margin="5" Height="230">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding FullName}" Height="20"/>
<TextBlock Text="{Binding Rights}" Height="20"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Border>
<Border x:Name="Room_menu" Background="Gray" CornerRadius="4" Margin="5">
<StackPanel Orientation="Vertical" Margin="10">
<Button Content="Add item" Margin="0,2,0,2"/>
<Button Content="Set changes" Margin="0,2,0,2"/>
<Button Content="Invite friend" Margin="0,2,0,2"/>
<Button Content="Rename room" Margin="0,2,0,2"/>
<Button Content="Delete room" Margin="0,2,0,2"/>
</StackPanel>
</Border>
</StackPanel>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Here is my Dictionnary Class that contains the RoomMenu:
public class Rooms : TabItem
{
public string Room_guid;
public string Room_name;
public string Primary_user_guid;
public string Room_version;
public Grid Room_grid;
public Canvas Room_canvas;
public RoomMenu Room_menu;
}
And this is when I call my ControlTemplate and Add it to my TabItem's Grid:
public void Set_rooms_interface()
{
foreach (KeyValuePair<string, Rooms> kvp in rooms_list)
{
rooms_list[kvp.Key].Room_menu = new RoomMenu();
rooms_list[kvp.Key].Room_canvas = new Canvas();
rooms_list[kvp.Key].Room_grid = new Grid();
//instance grid columns
rooms_list[kvp.Key].Room_grid.ColumnDefinitions.Add(new ColumnDefinition() {Width = new GridLength(900)});
rooms_list[kvp.Key].Room_grid.ColumnDefinitions.Add(new ColumnDefinition());
//Refreshing room canvas
rooms_list[kvp.Key].Room_canvas.Height = rooms_list[kvp.Key].Room_grid.ActualHeight;
rooms_list[kvp.Key].Room_canvas.Width = rooms_list[kvp.Key].Room_grid.ActualWidth;
rooms_list[kvp.Key].Room_canvas = refresh_canvas(kvp.Key);
Grid.SetColumn(rooms_list[kvp.Key].Room_canvas, 0);
Grid.SetColumn(rooms_list[kvp.Key].Room_menu, 1);
//Add Canvas to Grid
rooms_list[kvp.Key].Room_grid.Children.Add(rooms_list[kvp.Key].Room_canvas);
rooms_list[kvp.Key].Room_grid.Children.Add(rooms_list[kvp.Key].Room_menu);
//Setting TabItem Name
rooms_list[kvp.Key].Header = rooms_list[kvp.Key].Room_name;
//Adding Grid to TabItem.Content
rooms_list[kvp.Key].Content = rooms_list[kvp.Key].Room_grid;
//Adding TabItem to TabControl
Room_tab.Items.Add(kvp.Value);
}
}
I'm sorry if the whole question is a bit long but it was the only way to explain clearly what I was trying to do. So if anyone could give me a hint or answer to do some databinding in a ControlTemplate it would greatly help me.
Thank You.
I think you started in the wrong direction when instantiating UI elements in code. The code behind should only contain one line assigning the people list to the current_room_friends DataContext.
Start with simpler examples of binding data to a ListBox like the beautiful planet example of Bea Stollnitz.
Is it possible to display the text in a TextBlock vertically so that all letters are stacked upon each other (not rotated with LayoutTransform)?
Nobody has yet mentioned the obvious and trivial way to stack the letters of an arbitrary string vertically (without rotating them) using pure XAML:
<ItemsControl
ItemsSource="Text goes here, or you could use a binding to a string" />
This simply lays out the text vertically by recognizing the fact that the string is an IEnumerable and so ItemsControl can treat each character in the string as a separate item. The default panel for ItemsControl is a StackPanel, so the characters are laid out vertically.
Note: For precise control over horizontal positioning, vertical spacing, etc, the ItemContainerStyle and ItemTemplate properties can be set on the ItemsControl.
Just in case anybody still comes across this post... here is a simple 100% xaml solution.
<TabControl TabStripPlacement="Left">
<TabItem Header="Tab 1">
<TabItem.LayoutTransform>
<RotateTransform Angle="-90"></RotateTransform>
</TabItem.LayoutTransform>
<TextBlock> Some Text for tab 1</TextBlock>
</TabItem>
<TabItem Header="Tab 2">
<TabItem.LayoutTransform>
<RotateTransform Angle="-90"></RotateTransform>
</TabItem.LayoutTransform>
<TextBlock> Some Text for tab 2</TextBlock>
</TabItem>
</TabControl>
I don't think there is a straighforward of doing this withought changing the way the system inherently laysout text. The easiest solution would be to change the width of the textblock and supply a few extra properties like this:
<TextBlock TextAlignment="Center" FontSize="14" FontWeight="Bold" Width="10" TextWrapping="Wrap">THIS IS A TEST</TextBlock>
This is hacky, but it does work.
Just use a simple LayoutTransform..
<Label Grid.Column="0" Content="Your Text Here" HorizontalContentAlignment="Center">
<Label.LayoutTransform>
<TransformGroup>
<RotateTransform Angle="90" />
<ScaleTransform ScaleX="-1" ScaleY="-1"/>
</TransformGroup>
</Label.LayoutTransform>
</Label>
It's doable:
Your TextBlock's TextAlignment property should be set to Center:
<TextBlock Name="textBlock1" TextAlignment="Center" Text="Stacked!" />
Then add NewLines between every character:
textBlock1.Text =
String.Join(
Environment.NewLine,
textBlock1.Text.Select(c => new String(c, 1)).ToArray());
(Uses System.Linq to create an array of strings from the individual characters in the original string. I'm sure there are other ways of doing that...)
Below XAML code changes the angle of text displayed in a textblock.
<TextBlock Height="14"
x:Name="TextBlock1"
Text="Vertical Bottom to Up" Margin="73,0,115,0" RenderTransformOrigin="0.5,0.5" >
<TextBlock.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform Angle="-90"/>
<TranslateTransform/>
</TransformGroup>
</TextBlock.RenderTransform>
</TextBlock>
the accepted answer suggested by Ray Burns does not work for me on .net 4.0. Here is how I did it:
pull in the mscorlib
xmlns:s="clr-namespace:System;assembly=mscorlib"
put in your usercontrol/window/page resources
<s:String x:Key="SortString">Sort</s:String>
and use it like this
<ItemsControl ItemsSource="{Binding Source={StaticResource SortString}}" Margin="5,-1,0,0" />
hope it helps!
create a stackpanel with a bunch ot textblocks that take one char
make the text container's max width to allow for one char only and wrap the text:
<TextBlock TextWrapping="Wrap" MaxWidth="8" TextAlignment="Center" Text="stack" />
Make an image and fill the block with the image, use photoshop or something designed to manipulate text instead of fiddling in code ?
This code allows to have vertical text stacking and horizontal centered letters.
<ItemsControl Grid.Row="1"
Grid.Column="0"
ItemsSource="YOUR TEXT HERE"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}"
HorizontalAlignment="Center"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Here's a way to insert a '\n' after every character in the text of the TextBlock, that way making it display vertically:
<TextBlock x:Name="VertTextBlock" Text="Vertical Text" Loaded="VertTextBlock_Loaded"></TextBlock>
Then, in the Loaded event handler, you say:
TextBlock tb = sender as TextBlock;
StringBuilder sb = new StringBuilder(tb.Text);
int len = tb.Text.Length * 2;
for (int i = 1; i < len; i += 2)
{
sb.Insert(i, '\n');
}
tb.Text = sb.ToString();
That solution was proposed by Lette, but I believe my implementation incurs less overhead.
<linebreak/> can be used to show data in two lines
You could also use the "RUN" binding
In the App.xaml file use something like this:
<Application x:Class="Some.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:commands="clr-namespace:Deridiam.Helper.Commands"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
ShutdownMode="OnMainWindowClose"
StartupUri="Views/MainWindow.xaml">
<Application.Resources>
<commands:HorizontalToVertical x:Key="HorizontalToVertical_Command"></commands:HorizontalToVertical>
<ControlTemplate x:Key="VerticalCell" TargetType="ContentControl">
<TextBlock Text="{TemplateBinding Content}" Foreground="Black"
TextAlignment="Center" FontWeight="Bold" VerticalAlignment="Center"
TextWrapping="Wrap" Margin="0" FontSize="10">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Loaded">
<i:InvokeCommandAction Command="{Binding ConvertToVerticalCmd, Source={StaticResource HorizontalToVertical_Command}}"
CommandParameter="{Binding RelativeSource={RelativeSource AncestorType={x:Type TextBlock}}}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBlock>
</ControlTemplate>
</Application.Resources>
Create the command class binded to the textblock using i:Interaction.Triggers on the Loaded event in the app.xaml example
namespace Deridiam.Helper.Commands
{
public class HorizontalToVertical
{
private ICommand _convertToVerticalCommand;
public ICommand ConvertToVerticalCmd =>
_convertToVerticalCommand ?? (_convertToVerticalCommand = new RelayCommand(
x =>
{
var tBlock = x as TextBlock;
var horizontalText = tBlock.Text;
tBlock.Text = "";
horizontalText.Select(c => c).ToList().ForEach(c =>
{
if (c.ToString() == " ")
{
tBlock.Inlines.Add("\n");
//tBlock.Inlines.Add("\n");
}
else
{
tBlock.Inlines.Add((new Run(c.ToString())));
tBlock.Inlines.Add(new LineBreak());
}
});
}));
}
}
Finally in the .xaml file where you want the vertical text to be shown
<ContentControl Width="15" Content="Vertical Text" Template="{StaticResource VerticalCell}">
</ContentControl>
Will result in:
Vertical Text
none of the above solutions solved my problem (some come close), so I'm here to post my solution and maybe help someone.
The accepted solution helped me, but the text is not aligned to the center.
<ItemsControl ItemsSource="{Binding SomeStringProperty, FallbackValue=Group 1}" Margin="5"
TextElement.FontSize="16"
TextElement.FontWeight="Bold"
TextBlock.TextAlignment="Center"
HorizontalAlignment="Center"
VerticalAlignment="Center" >
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate >
<TextBlock Text="{Binding }" HorizontalAlignment="Center" />
</DataTemplate>
</ItemsControl.ItemTemplate>
I will offer a solution based on the converter:
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Windows.Data;
using System.Windows.Markup;
namespace Converters
{
[ValueConversion(typeof(object), typeof(string))]
public class InsertLineBreakConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (parameter != null)
value = parameter;
if (value == null)
return null;
if (!(value is string str))
str = value.ToString();
return string.Join(Environment.NewLine, (IEnumerable<char>) str);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
public static InsertLineBreakConverter Instance { get; } = new InsertLineBreakConverter();
}
public class InsertLineBreakConverterExtension : MarkupExtension
{
public override object ProvideValue(IServiceProvider serviceProvider)
=> InsertLineBreakConverter.Instance;
}
}
Usage examples:
<TextBlock Text="{Binding Property, Converter={cnvs:InsertLineBreakConverter}}"/>
<TextBlock Text="{Binding Converter={cnvs:InsertLineBreakConverter}, ConverterParameter='Some Text'}"/>