TextBlock binding format - c#

How could I achieve this behavior in my ComboBox items: (n): Name
Where n and Name are two bindable properties. Right now I have n Name
This is my code:
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock>
<Run Text="{Binding n}" />
<Run Text="{Binding Name}" />
</TextBlock>
</DataTemplate>
</ComboBox.ItemTemplate>
I think that adding two <Run Text="("/>, etc it can be done but there must be something more elegant in XAML.

Ok it was easy:
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}({0}): - {1}">
<Binding Path="n" />
<Binding Path="Name" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</DataTemplate>
</ComboBox.ItemTemplate>

Another way is using multiple TextBlocks like so:
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=...}"></TextBlock>
<TextBlock Text="{Binding Path=...}"></TextBlock>
</StackPanel>
</DataTemplate>
You can replace the StackPanel with a WrapPanel or whatever you like.

Related

WPF Binding in textblock does not work but in its tooltip does

I have a weird issue.
In my application (witten with C# .net framework 4.8 with Microsoft's MVVM toolkit) I have a ListView bound to a BindingList<VisualMachine>, everything works as expected.
Now I wanted to add to the Itemtemplate a DockPanel with data from another BindingList<PreviewParameter> (another property of the original VisualMachine object ).
This is when weirdness starts: In this new ItemTemplate I have a Grid that contains an Image, a TextBlock and a Tooltip. The TextBlock and the Tooltip are bound to the same object, but only the ToolTip actually show data!
I feel like it's some DataContext Issue, but I am not able to pin it... Can anybody give me some advice?
Thanks!
The code:
<ListView Name="MachinesListView" Margin="2" HorizontalContentAlignment="Stretch" BorderThickness="0" DockPanel.Dock="Top" ItemsSource="{Binding Path=Machines}" PreviewMouseRightButtonDown="ListView_PreviewMouseRightButtonDown" SelectedItem="{Binding Path=SelectedMachine}">
<ListView.ItemTemplate>
<DataTemplate>
<!-- Other stuff -->
<DockPanel>
<!--#region PREVIEW PARAMETERS PANEL-->
<WrapPanel HorizontalAlignment="Stretch" DockPanel.Dock="Bottom" Visibility="{Binding Path=PreviewParameters.Count, Converter={StaticResource CountToVisConverter}}">
<ListView ItemsSource="{Binding Path=PreviewParameters}">
<ListView.ItemTemplate>
<DataTemplate>
<Grid MinWidth="50">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="25"/>
<ColumnDefinition Width="Auto" MinWidth="25"/>
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Source="{Binding Path=Icon, Converter={StaticResource ResourceKey=BmpToBmpImageConverter}}"/>
<TextBlock Grid.Column="1" MaxWidth="100" DataContext="{Binding}">
<TextBlock.Text>
<!-- THIS DOES NOT APPEAR -->
<MultiBinding StringFormat="{}{0} [{1}]}">
<Binding Path="Parameter.VisualizedValue"/>
<Binding Converter="{StaticResource ParamToEnumDescConverter}" Path="Parameter"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
<Grid.ToolTip>
<TextBlock MaxWidth="100" TextWrapping="Wrap">
<TextBlock.Text>
<!-- THIS DOES APPEAR -->
<MultiBinding StringFormat="{}{0} [{1}] - {2} TEST:{3} {4}">
<Binding Path="Parameter.Reference"/>
<Binding Path="Parameter.SetupIndex"/>
<Binding Path="Description"/>
<Binding Path="Parameter.VisualizedValue"/>
<Binding Converter="{StaticResource ParamToEnumDescConverter}" Path="Parameter"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</Grid.ToolTip>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</WrapPanel>
<!-- Other stuff -->
</DockPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
What happens:
I found it.
There was a } in the StringFormat property of the TextBlock's MultiBinding.
So instead of
<MultiBinding StringFormat="{}{0} [{1}]}">
it should be
<MultiBinding StringFormat="{}{0} [{1}]">
And BAM! Now it works.
I'll leave the question as the following reminder to anybody: "Write your code, review it, than go take a coffee o chat a little and then come back. You'll be amazed on how blind you could be."

Making a ToolTip not visible

There is an icon that I want to always be visible, but I want the tooltip to be conditionally visible. Here is the code that I currently have:
<TextBlock Grid.Row="2"
Grid.Column="0"
VerticalAlignment="Center"
FontSize="15"
Visibility="{Binding IsConnected, Converter={StaticResource BooleanToVisibilityConverter}}">
<fa:ImageAwesome Icon="{Binding Path=BatteryLevelIcon, UpdateSourceTrigger=PropertyChanged}"
Height="20"
Width="20"
Foreground="Green"
Visibility="{Binding IsConnected, Converter={StaticResource BooleanToVisibilityConverter}}" />
<ToolTipService.ToolTip>
<TextBlock Visibility="{Binding IsCharging, Converter={StaticResource InvertedBooleanToVisibilityConverter}}">
<TextBlock.Text>
<MultiBinding StringFormat="{}{0}%">
<Binding Path="BatteryPercentage" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</ToolTipService.ToolTip>
</TextBlock>
So, I want the tooltip to only show up when IsCharging is false. The issue that I am having is that because the Visibility property is on the tooltip textblock instead of the tooltip itself, setting it to not visible only gives me a empty tooltip, instead of the tooltip not appearing at all. I have tried defining the content of the tooltip (textblock) in UserControls.Resources and then setting the textblock and IsEnabled, but it gave me the error:
a value of type tooltipservice cannot be added to a collection or dictionary of type inlinecolection
It doesn't seem there is an easy way to set the visibility for the tooltip. If anyone has any suggestions it would be greatly appreciated!
You could use ToolTipService.IsEnabled property for the purpose
ToolTipService.IsEnabled="{Binding IsToolTipVisible}"
Where IsToolTipVisible Where is the View Model property which dictates where to enable the tooltip
Complete Code
<TextBlock Grid.Row="2" ToolTipService.IsEnabled="{Binding IsToolTipVisible}"
Grid.Column="0"
VerticalAlignment="Center"
FontSize="15"
Visibility="{Binding IsConnected, Converter={StaticResource BooleanToVisibilityConverter}}">
<fa:ImageAwesome Icon="{Binding Path=BatteryLevelIcon, UpdateSourceTrigger=PropertyChanged}"
Height="20"
Width="20"
Foreground="Green"
Visibility="{Binding IsConnected, Converter={StaticResource BooleanToVisibilityConverter}}" />
<ToolTipService.ToolTip>
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}{0}%">
<Binding Path="BatteryPercentage" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</ToolTipService.ToolTip>
</TextBlock>

How to set a secondary control MaxWidth property to the same as another in a different container

I have this StackPanel in one grid on my form:
<StackPanel x:Name="panelWeelyBibleReading" Grid.Row="2" Grid.Column="0" Margin="2">
<Label>Bible Reading for Week:</Label>
<TextBox x:Name="textWeeklyBibleReading">PSALMS 60-68</TextBox>
</StackPanel>
<StackPanel Grid.Row="3" Grid.Column="0" Margin="2">
<Label>Opening Song:</Label>
<ComboBox x:Name="comboSongOpen" ItemsSource="{StaticResource SongTitles}">
<ComboBox.ItemTemplate>
<DataTemplate DataType="local:SongTitleItem">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Number, StringFormat='000 - '}" />
<TextBlock Text="{Binding Title}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
<ComboBox.MaxWidth>
<Binding Path="ActualWidth"
ElementName="textWeeklyBibleReading"/>
</ComboBox.MaxWidth>
</ComboBox>
</StackPanel>
Further down the form in a different grid I have this :
<StackPanel Grid.Row="3" Grid.Column="0" Margin="2">
<Label>Closing Song:</Label>
<ComboBox x:Name="comboSongEnd" ItemsSource="{StaticResource SongTitles}">
<ComboBox.ItemTemplate>
<DataTemplate DataType="local:SongTitleItem">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Number, StringFormat='000 - '}" />
<TextBlock Text="{Binding Title}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
<ComboBox.MaxWidth>
<Binding Path="ActualWidth"
ElementName="panelWeeklyBibleReading.textWeeklyBibleReading"/>
</ComboBox.MaxWidth>
</ComboBox>
</StackPanel>
Initially I tried using the same "textWeeklyBibleReading" for the MaxWidth in the second combo. But it doesn't work. No warnings. Just doesn't work. So I thought about applying a name to the previous StackPanel in teh hopes I could use it as some kind of access point. But it still doesn't work.
So my problem is that I need to set the MaxWidth on the second combo, which is in a different grid, but using the value that was calculated on the first grid combo. Am I making sense?
I would show the complete form markup if it helps.
You should edit to:
<ComboBox.MaxWidth>
<Binding Path="Width"
ElementName="textWeeklyBibleReading"/>
</ComboBox.MaxWidth>
<Binding Path=Width, ElementName=textWeeklyBibleReading/>
cause there is no property such as ActualWidth, instead it should be Width. And there is no need to write container name panelWeeklyBibleReading, just write ElementName that you need.
Update:
<ComboBox.ItemTemplate>
<DataTemplate DataType="local:SongTitleItem">
<StackPanel Orientation="Horizontal" MaxWidth="{Binding Path=Width,
ElementName=textWeeklyBibleReading}">
<TextBlock Text="{Binding Number, StringFormat='000 - '}" />
<TextBlock Text="{Binding Title}" />
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
You should set MaxWidth of StackPanel of ComboBox cause outer StackPanel``(<StackPanel Grid.Row="3" Grid.Column="0" Margin="2">) which contains your ComboBox automatically sets Width to the outer StackPanel to your ComboBox. So I suggest to bind Width of your ComboBox to its ItemTemplate. Cause ItemTemplate has Data/template, then it is better to bind Width of ComboBox to StackPanel located into your DataTemplate.

Show multiple columns from database in one combobox

I want to show in one combobox content from two database columns. I would like to show "Name Surname" but I don't know how. I'm working in C# (.NET) using MVVM pattern. "Name" and "Surname" are fields from table "tblGuests".
Thanks in advance,
Vladimir
You could create an ItemTemplate for the ComboBox that binds to all the properties you want to show.
<ComboBox ItemsSource="{Binding}">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=FirstName}" Padding="10,0,0,0"/>
<TextBlock Text="{Binding Path=LastName}" Padding="10,0,0,0"/>
</StackPanel>
<DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
You could even create a UserControl that can be re-used and use that:
<PersonView>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=FirstName}" Padding="10,0,0,0"/>
<TextBlock Text="{Binding Path=LastName}" Padding="10,0,0,0"/>
</StackPanel>
</PersonView>
<ComboBox ItemsSource="{Binding}">
<ComboBox.ItemTemplate>
<DataTemplate>
<PersonView/>
<DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Keep a string list property in Viewmodel,
populate that property in a data loading method, by combining name and surname strings,
bind string property to combo box,
<ComboBox Name="ComboBox1" ItemsSource="{Binding YourStringListProperty}"/>
Another option could be to use MultiBinding something like this
<TextBlock Name="textBox2" DataContext="{StaticResource NameListData}">
<TextBlock.Text>
<MultiBinding Converter="{StaticResource myNameConverter}"
ConverterParameter="FormatLastFirst">
<Binding Path="FirstName"/>
<Binding Path="LastName"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
This code was taken directly from msdn. Refer to it for more details

Bind Textblock text to 2 different properties

I have a binded treeview that displays one of the properties (namely, the displayname) of the treeviewitem (which are custom viewmodel's of an object).
Here is the associated xaml:
<local:ExtendedTreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding SubOrganLocations}">
<TextBlock Text="{Binding OrganDisplayName}" >
</TextBlock>
</HierarchicalDataTemplate>
</local:ExtendedTreeView.ItemTemplate>
What I want is to be able to display another property next to the display name in parenthesis.
so instead of the treeview looking like this:
Root
-sub node1
--subsub node1
-sub node2
I want it to look like this:
Root (Type1)
-sub node1 (Type2)
--subsub node1 (Type 3)
-sub node2 (Type 1)
How can I accomplish this? Using multi-binding?
Try this:
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}{0} ({1})">
<Binding Path="{YourBindingHere}" />
<Binding Path="{YourBindingHere}" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
You could just use multiple text blocks
<local:ExtendedTreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding SubOrganLocations}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding OrganDisplayName}" />
<TextBlock Grid.Column="1" Text="{Binding TypeName}" />
</Grid>
</HierarchicalDataTemplate>
</local:ExtendedTreeView.ItemTemplate>
Or you could add a property to your view model which calculate the full name internally and just bind to that.
Or use <Run/>:
<TextBlock>
<Run Text="{Binding OrganDisplayName}"/>
<Run Text=" ("/>
<Run Text="{Binding TypeName}"/>
<Run Text=")"/>
</TextBlock>

Categories