How to add a tooltip using IValueConverter - wpf

I am looking for a solution to add a tooltip for a button using value converter.
This is because some part/text of this tooltip is calculated dynamically.
For instance i have an application with some "launchable" tasks in it in such a way that clicking any/all of these tasks launches another application.
In this task list, there is a button "Launch Tasks" with count depending upon the no. of tasks selected to launch.I need to show a tooltip for this button only.Like:
"Launch Tasks(2)", this is for two tasks selected.
Can someone please help in writing a converter for the same and then how to bind the same in XAML?
Update:
Earlier it is something like as below, but problem is tooltip shown is not upto the standards and not clearly visible, so i thought of removing the same and used converter instead.
<ToolTipService.ToolTip>
<ToolTip>
<StackPanel Orientation="Horizontal">
<TextBlock x:Name="ttlblActivityCount" Text="{Binding LaunchTaskButtonTitle, Source={StaticResource ResourceData}}" />
<TextBlock x:Name="ttlblActivityCountStart"
Margin="2,0,0,0"
Text="("/>
<TextBlock x:Name="tttxtActivityCount" Text="{Binding Path=SelectedActivitiesCount}"/>
<TextBlock x:Name="ttlblActivityCountEnd"
FontWeight="Bold"
Text=")" />
</StackPanel>
</ToolTip>
</ToolTipService.ToolTip>

Using a StackPanel to artificially combine a string is yes pretty much something you don't want to do. However you don't have to use an IValueConverter for this
If you have a property for SelectedActivitiesCount and you want to bind it's tooltip with some static text and the property a simple example could be:
<Button Content="Launch Tasks">
<Button.ToolTip>
<TextBlock Text="{Binding SelectedActivitiesCount, StringFormat=Launch Tasks({0})}" />
</Button.ToolTip>
</Button>
^^ With this output would look like: "Launch Tasks(2)" where SelectedActivitiesCount -> 2
If the text("Launch Tasks") is also dynamic:
<Button Content="Launch Tasks">
<Button.ToolTip>
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}{0} ({1})">
<Binding Path="LaunchTaskButtonTitle" Source="{StaticResource ResourceData}" />
<Binding Path="SelectedActivitiesCount" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</Button.ToolTip>
</Button>
^^ With this output would look like: "Launch Tasks(2)" where SelectedActivitiesCount -> 2, LaunchTaskButtonTitle -> Launch Tasks
Choose whichever method is applicable for you.

Related

Registering a Region within an ItemTemplate

I'm writing a WPF application with Prism and I'm using MVVM,
Now, I have a view with Items Control, and I want each item to have a certain look, with an option to add a unique context menu per item.
so it look's like this so far:
<ItemsControl Grid.Column="1" ItemsSource="{Binding DeviceHolders}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Image Name="image" Source="{Binding ImageIndex, Converter={StaticResource ImageIndexToLargeImageBitmapSource}}" Margin="5" VerticalAlignment="Center" HorizontalAlignment="Center">
<Image.ContextMenu>
<ContextMenu <--THIS AS A UNIQUE REGION WHICH THE REGION NAME WILL BE string.format("{0}-{1}", "DeviceHolderRegion", DeviceHolder.ID)-->/>
</Image.ContextMenu>
</Image>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
As I wrote in the code, I want the context menu to register as a region with a unique name (for each device holder object I want to add a different context menu based on his type).
is there a way to do so?
Thanks.
I didn't know you could use a ContextMenu as a region - you learn something new every day!
Anyway, try the following:-
<ContextMenu>
<regions:RegionManager.RegionName>
<MultiBinding StringFormat="{}{0}-{1}">
<Binding Path="DeviceHolderRegion" />
<Binding Path="DeviceHolder.ID" />
</MultiBinding>
</regions:RegionManager.RegionName>
</ContextMenu>
I haven't tried running it, but VS XAML editor doesn't complain about the syntax, which is a promising start.

Specifying a Button Content that has mix of text and a Binding path

How do you specify the Content of a button that is a mix of some TEXT and a Binding path?
Like this:
<Button Content= "TEXT" + "{Binding Path=ButtonContent}"
For most cases you can use StringFormat in the Bindings, like for a TextBlock
<TextBlock Text="{Binding ElementName=textBox,
Path=Text,
StringFormat='{}{0} - Added Text'}"/>
However, this has no effect on a ContentControl (which Button inherits from). Instead, you can use ContentStringFormat
<Button Content="{Binding ElementName=textBox,
Path=Text}"
ContentStringFormat="{}{0} - Added Text"/>
Also, for
ContentControl you use ContentStringFormat
HeaderedContentControl you use HeaderStringFormat
ItemsControl you use ItemStringFormat
Something like this:
<Button>
<Button.Content>
<TextBlock Text="{Binding SomeBindingPath, StringFormat='Some text {0}'}"/>
</Button.Content>
</Button>
OR
<Button>
<Button.Content>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Some Text"/>
<TextBlock Text="{Binding SomeBindingPath}"/>
</StackPanel>
</Button.Content>
</Button>
Basically, you can put any content inside a button using the approach above.
Building on the other answers, this is a little more terse:
<Button Content="{Binding FirstName, StringFormat='Click here, {0}!'}" />

Pattern for working with a form in Silverlight 4? (How to get references to XAML elements)

I have a form:
<StackPanel Orientation="Horizontal" Visibility="{Binding Editable, Converter={StaticResource visibilityConverter}}"
ToolTipService.ToolTip="Add new topic to this group">
<sdk:AutoCompleteBox Width="160" ItemsSource="{Binding ElementName=LayoutRoot, Path=DataContext.TopicNames}" />
<Button Click="addTopicButton_Click">
<Image Source="Images/appbar.add.rest.png" />
</Button>
</StackPanel>
This form appears in a DataTemplate for an ItemsControl. I'm not sure what the best way is to get the data from the AutoCompleteBox when the button is clicked. I can't give the elements x:Name attributes, because they're in a template (right?).
How can I get around this? The Click event will give me the Button, but I need a reference to the text box. Use the Button's parent, then look through the children for the Textbox? If I factored this out into its own UserControl, I could set x:Name values, but I'd rather not do that.
Any other ideas?
Update: Here is another example of such a problem:
<ListBox x:Name="topicList"
ItemsSource="{Binding Id, Converter={StaticResource topicGroupIDConverter}}"
SelectionChanged="ListBox_SelectionChanged"
HorizontalAlignment="Stretch">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}"
Width="150"
VerticalAlignment="Center"
ToolTipService.ToolTip="{Binding Description}"
ToolTipService.Placement="Right" />
<Button ToolTipService.ToolTip="Remove this topic from this group"
Visibility="{Binding ElementName=topicList,
Path=DataContext.Editable,
Converter={StaticResource visibilityConverter}}"
Click="removeTopicButton_Click"
HorizontalAlignment="Right"
Margin="10,0">
<Image Source="Images/appbar.cancel.rest.png" />
</Button>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
When the button is clicked, I want to access topicList.DataContext. However, topicList itself is a DataTemplate in an ItemsControl, so I can't access it using its name from code-behind. How else can I do this?
You can add a property, say SelectedItemInAutoCompleteBox, to your presenter, and then can bind it to the SelectedItem property of AutoCompleteBox, using Mode=TwoWay, like this,
<sdk:AutoCompleteBox SelectedItem="{Binding Path=DataContext.SelectedItemInAutoCompleteBox, Mode=TwoWay}" ... />
You may try the same approach with Text property of AutoCompleteBox, also. See if it solves your problem.:-)
You have several choices:
If you're on Silverlight 5, use the AncestorBinding
Otherwise, use a Silverlight 4 AncestorBinding hack (it doesn't look pretty)
Or you could try DataContextProxy, which stores the DataContext in a resource so that it is accessible. Note: you should set the DataContextProxy as a Resource of topicList ListBox, not the UserControl as in Dan Wahlin's example.

WPF StringFormat databinding text not appearing

I am trying to get the header text of a TreeviewItem to be set in the binding to an XML source. Everything is working fine except the only thing that appears in the header is the text I'm binding to and nothing else in the string format. Example:
<HierarchicalDataTemplate x:Key="LogDataTemp" ItemsSource="{Binding Path=log}">
<TreeViewItem>
<TreeViewItem.Header>
<Binding Path="Attribute[level].Value" StringFormat="TEST \{0\}" />
</TreeViewItem.Header>
</TreeViewItem>
</HierarchicalDataTemplate>
In this case the level value appears but nothing else. I have tried dozens of different ways of approaching this and it seems that nothing works.
Don't escape the braces in the StringFormat. You want to apply the formatting to the 0th-element in your binding.
For instance, with a simple property called "Level":
<TextBlock x:Name="txtUnformatted" Grid.Row="0" Foreground="White" >
<TextBlock.Text>
<Binding Path="Level" />
</TextBlock.Text>
</TextBlock>
<TextBlock x:Name="txtFormatted" Grid.Row="1" Foreground="White">
<TextBlock.Text>
<Binding Path="Level" StringFormat="Test {0:000000}" />
</TextBlock.Text>
</TextBlock>
And the result is something like:
Update
Also, the default implementation of the Header, when you don't add any controls, is a simple ContentPresenter, which doesn't apply formatting. To work around this, simply put a TextBlock into the header, and bind the text you want formatted to that.
<HierarchicalDataTemplate x:Key="LogDataTemp" ItemsSource="{Binding Path=log}">
<TreeViewItem>
<TreeViewItem.Header>
<TextBlock>
<TextBlock.Text>
<Binding Path="Attribute[level].Value"
StringFormat="TEST {0}" />
</TextBlock.Text>
</TextBlock>
</TreeViewItem.Header>
</TreeViewItem>
</HierarchicalDataTemplate>
It is perfectly acceptable (and commonly done) to put controls into a header control (for instance, a grid containing an image and a label). The beauty of WPF.

WPF Commands Buttons ListBoxItems

I Have a listbox defined like below :
<ListBox x:Name="lstMedias" ItemsSource="{Binding Medias}" Width="Auto" Height="Auto">
<ListBox.ItemTemplate>
<DataTemplate>
<Button Content="{Binding Name}" Tag="{Binding Name}" Click="Button_Click" Command="{Binding Path=LoadSimpleMoviePopupCommand}">
<Button.Resources>
<Converters:LoadMovieMultiConverter x:Key="LoadMovieMultiConverter" />
</Button.Resources>
<Button.CommandParameter>
<MultiBinding Converter="{StaticResource LoadMovieMultiConverter}">
<MultiBinding.Bindings>
<Binding ElementName="DragDropCanvas" />
<Binding Path="Tag" RelativeSource="{RelativeSource Self}" />
</MultiBinding.Bindings>
</MultiBinding>
</Button.CommandParameter>
</Button>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
When Trying to call command LoadSimpleMoviePopupCommand, command is not called, but when calling click event, event is raised.
Do You have an idea why ? It is a normal behavior ? Do we have to trick like ListBoxItem doubleclick ?
Probably because the binding failed. Check the output window of VS and see if there are any binding errors. I suspect the LoadSimpleMoviePopupCommand property is not on your data item class (ie. your Media class).
had the same problem, try this
<Button Command="{Binding DataContext.YourCommand,RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}"
it's quite normal, he can't find your command binding inside the listbox because you set something like
<DataTemplate DataType ...
in that listbox so he'll be looking for that binding inside the datatype and not the viewmodel (I assume :)

Resources