I have this code:
<ribbon:Button Label="Hello" />
I wanted to bind its tooltip to Label like:
<ribbon:Button Label="Hello" ToolTip="Hello" />
I have already tried creating style with the following info, but failed:
<Style TargetType="{x:Type ribbon:Button}">
<Setter Property="ToolTip" Value="{Binding Text}" />
</Style>
Please tell me how can I fix this. Instead of ribbon:Button, normal button code be used and I want to bind its tooltip property with its Content property.
Edit: One more thing after trying, if i set the Value property of Setter inside style without any binding, it works fine. Eg:
<Style TargetType="{x:Type ribbon:Button}">
<Setter Property="ToolTip" Value="This will show" />
</Style>
But binding is not applied here. So problem arises only when binding is done :(
Of course your style won't work, because you always bind to the properties of your DataContext, which i doubt is your Control itself.
<Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=Text}"/>
should work fine.
The golden rule for binding is: look for binding errors in the debug output.
Secondly, you are binding Text, where everywhere else you use the property label.
Thirdly, understand that the basis for Binding is the DataContext. You can give Xaml elements a name, then use the Binding syntax based on ElementName to bind to FrameworkElement properties.
Related
I have a collection of objects that have different rendering options: They can be simple text, editable text, comboboxes, or event a mixed bag (like a comboBox where items are usually text but with images for specific values).
I managed to show everything correctly by using ContentTemplateSelector inside a ContentPresenter node inside the DataTemplate of the ListViewItem.ItemTemplate:
<ContentPresenter
Grid.Row="1"
Grid.Column="1"
Content="{Binding .}"
ContentTemplateSelector="{DynamicResource ResourceKey=RenderTemplateSelector}"/>
(note that everything is inside the DataTemplate of a ListView.ItemTemplate)
All is good until I change the value of said property and need to change the template, for instance going from a image to a text.
The VM does update correctly the values, but nothing happens in the GUI.
Looking around here there are a few methods (using a Converter (bound to which property??), defining a Style (i think is not relevant, since i must show different controls, not change properties of the same one), using an AttachedProperty (I don 't understand really well how attached properties work, but from what I saw I should have a ContentControl node, which I don't...) but nothing seems what I need.
So, a recap: I have a ListView that has a DataTemplate definded for each ListViewItem that contains another DataTemplate that needs to change based on a properti of the ListViewItem object. I managed to achieve this with a ContentTemplateSelector, but that is assigned at the beginning and then never changed.
You could try to replace the ContentPresenter with a ContentControl that has a Style with data triggers that sets the ContentTemplate, .e.g.:
<ContentControl Content="{Binding}">
<ContentControl.Style>
<Style TargetType="ContentControl">
<Style.Triggers>
<DataTrigger Binding="{Binding YourProperty}" Value="Type1">
<Setter Property="ContentTemplate" Value="{StaticResource template1}" />
</DataTrigger>
<DataTrigger Binding="{Binding YourProperty}" Value="Type2">
<Setter Property="ContentTemplate" Value="{StaticResource template2}" />
</DataTrigger>
<!-- ... -->
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
I am running into a problem with WPF UI wherein I need to set the border of a GroupBox control based on the fact if there is any checkbox inside the GroupBox that has been unchecked. I have tried writing some code but that didn't work, I am new to WPF and I tried using a style to solve the problem but that didn't work well with me. The code looks as follows -:
<GroupBox Grid.Row="6" Grid.ColumnSpan="3" Header="View Actions" >
<GroupBox.Style>
<Style TargetType="GroupBox" d:DataContext="{d:DesignInstance ActionsViewModels:IActionViewModel}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsEnabled}" Value="False">
<Setter Property="BorderBrush" Value="Red" />
<Setter Property="BorderThickness" Value="2"/>
</DataTrigger>
</Style.Triggers>
</Style>
</GroupBox.Style>
<ContentControl Content="{Binding ViewActionsVM}"/>
</GroupBox>
Just FYI, the is used to populate the GroupBox with objects which have a text and checkbox component inside them and look something like this
Now what I want to be able to do is when one unchecks this checkbox I want to be able to add a red border around the Groupbox in which its contained. The content shown in the image comes from the ContentControl binding that we have in our project. To add to the description of the Content, the content describes an Action to be performed and has a property called as IsEnabled that I am using in the DataTrigger to decide whether to add a border or not.
I have a functional binding on my TextBox which acts as a searbar.
However, when I add the following trigger applied on the same binding (The first trigger), it stops the binding.
<TextBox>
<TextBox.Style>
<Style TargetType="TextBox">
<Setter Property="Text" Value="{Binding Path=SearchFilterString, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<Style.Triggers>
<!-- 1st trigger -->
<DataTrigger Binding="{Binding Path=SearchFilterString}" Value="">
<Setter Property="Text" Value="Type in part name to search."/>
</DataTrigger>
<!-- 2nd trigger -->
<Trigger Property="IsFocused" Value="true">
<Setter Property="Text" Value="{x:Null}"/>
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
I also included the second trigger, to make sure after I fix the problem with the first one it won't create a endless loop situation. So please comment on that one as well.
The purpose of these two triggers is to show some guidline inside the TextBox to describe what is this texbox about and the guidline disapears as soon as TextBox gains focus and user attempts to type in the search keyword.Let me know if you believe there is a better approach on doing the same thing.
Your binding won't work, because you are overriding it with your trigger's setter: You are setting the Text property of it to a value, while you are binding the same Text property to the view model. Both things can't work at the same time.
Essentially you're trying to create something that is called "watermark" on a textbox. I like the following the solution in particular, because it doesn't modify the TextBox itself but layers an adorner ontop of it:
Watermark Behavior for TextBox
You are looking for a watermark textbox. The standard WPF TextBox does not support this behavior.
However, there are 3rd party controls available such as the one pointed out by Frank: http://wpfplayground.com/2014/06/30/watermark-behavior-for-textbox/
Ways to do your own can be found at Watermark / hint text / placeholder TextBox in WPF
Finally, you can always just overlay your own TextBox or TextBlock over the real one and hide it on focus, which will do basically the same thing.
This is how I achieved it using Brad's idea.
I simply put a Label with the watermark I wanted and overlapped my TextBox on top of it. All I am doing is setting the TextBox's Background property to Transparent when it's binding content is empty. When this happens you can see the label on the back.
Hence, the moment you start typing watermark disappears.
XAML
<!-- Watermark Label -->
<Label
Foreground="Gray"
Content="Type the part name to start the search."
/>
<!-- Search TextBox -->
<TextBox Grid.Column="0"
HorizontalAlignment="Stretch"
>
<TextBox.Style>
<Style TargetType="TextBox">
<Setter Property="Text" Value="{Binding Path=SearchFilterString, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=SearchFilterString}" Value="">
<Setter Property="Background" Value="Transparent"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
Outcome
I wonder what the best design is to show different content dynamically in a list view.
What I want is (e.g.) depending on a radio button, a list view be filled with items (setting ItemsSource, changing column width, names and the row information itself).
What I'm currently doing is dynamically changing all the list view properties.
I wonder if it would be better to use multiple list views (maybe even as user controls), all on the same window position and hide all non-used.
Also, since I'm using MVVM Light/WPF I want to easily connect it to the XAML code if possible.
If changes in ItemsSource occur in time (or you want change it depending on some conditions like RadioButton's IsChecked property) you need to reflect on change your DataTemplate. The way out is to create DataTrigger which will swap your DataTemplates based on some criteria.
<ListView>
<ListView.Style>
<Style TargetType="ListView">
<Setter Property="ItemsSource" Value="{Binding InitalSource}"/>
<Setter Property="ItemTemplate" Value="{StaticResource InitialDataTemplate}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=RadioButton, Path=IsChecked}" Value="True">
<Setter Property="ItemsSource" Value="{Binding AnotherSource}"/>
<Setter Property="ItemTemplate" Value="{StaticResource AnotherDataTemplate}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ListView.Style>
</ListView>
Whenever condition of DataTrigger stops being true all changes made by Setters vanish, by default, therefore you do not need to add another DataTrigger in case of False value for RadioButton's IsChecked.
I'm probably missing something because what I do is suposed to work I think. I'm trying to bind the ElementName of a value to change when trigered.
here's the code (it is in the style):
<ContentPresenter>
<ContentPresenter.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding Tick}" Value="True">
<Setter Property="FocusManager.FocusedElement" Value="{Binding ElementName={Binding FieldNameFocus}}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ContentPresenter.Style>
</ContentPresenter>
And get this error:
Error 2 A 'Binding' cannot be set on the 'ElementName' property of type 'Binding'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject. C:\Users\xavier\Documents\Visual Studio 2012\Projects\Test_Validation\Test_Validation\MainWindow.xaml 1 2 Test_Validation
Maybe I'm not in the right path though... I just want to have focusedElement to change according to FieldNameFocus when Tick becomes True. (Both are in my dataContext)
Thanks in advance.
Your binding should look like this: Value="{Binding ElementName=YourElementName, Path=PropertyOfTheElement}"
Example binding by ElementName:
<TextBox Name="tbx1" Text="TextBox"/>
<TextBox Name="tbx2" Text="{Binding ElementName=tbx1, Path=Text}"/>
Hello the error is pretty clear, you cannot use Binding on with ElementName. When using ElementName you should provide the name of a control present in your xaml File as the previous post showed. As your trigger is bind to a boolean value you might want to replace "ElementName={Binding FieldNameFocus}" by
"ElementName=controlNameOnWhichYouWantToSetFocus".
Eg <Textbox x:Name="ControlIWantFocusOnWhenTickIstrue"> then in your trigger
<Setter Property="FocusManager.FocusedElement" Value="{Binding ElementName="ControlIWantFocusOnWhenTickIstrue"/>