How is the right way to bind dynamically a TextBox to a Slider?
The idea is to have many textboxes. When the user click over a TextBox, it changes his Background Color (showing thats it has the focus) and then if the user change the value of the Slider, the Text property of the Selected Textbox should change.
I would so this by embedding the TextBoxes in a ListBox. That way you can use list box to handle the definition of what is focused by its SelectedItem, and then bind the slider to the listboxes selecteditem too.
As #AlSki mentioned you could use a ListBox to hold all your TextBoxes and bind to the SelectedItem
Example:
<StackPanel>
<Slider Value="{Binding SelectedItem.Text, ElementName=listbox}"/>
<ListBox Name="listbox">
<TextBox />
<TextBox />
<TextBox />
<TextBox />
</ListBox>
</StackPanel>
Or if the TextBoxes are layed out in a fashion that cant be used with an ItemsControl you could do this with by creating a TextBox Style and setting the Binding to the Slider in a Trigger
Example:
<StackPanel>
<StackPanel.Resources>
<Style TargetType="TextBox">
<Setter Property="Text" Value="{Binding RelativeSource={RelativeSource Self}, Path=Text, Mode=OneWay}" />
<Setter Property="Background" Value="White" />
<Style.Triggers>
<Trigger Property="IsFocused" Value="true">
<Setter Property="Background" Value="Yellow" />
<Setter Property="Text" Value="{Binding ElementName=slider, Path=Value, Mode=OneWay}" />
</Trigger>
</Style.Triggers>
</Style>
</StackPanel.Resources>
<Slider Name="slider" Focusable="False"/>
<TextBox />
<TextBox />
<TextBox />
<TextBox />
</StackPanel>
Related
I have multiple RadioButton where a single one is composition of an Image and a TextBlock wrapped with StackPanel
<RadioButton
Tag="0"
Grid.Column="0"
Grid.Row="0"
Name="rdbOutlook">
<StackPanel>
<Image Source="Resources/outlook.png"
Stretch="Fill"
Width="50"/>
<TextBlock Text="Outlook/Hotmail" />
</StackPanel>
</RadioButton>
I want to set the StackPanel background to such a color when the RadioButton is checked.
How could do that by using Window.Resources to avoid code duplication and ease the modification?
You can use the following code for all RadioButtons containing a StackPanel:
<Window.Resources>
<Style TargetType="StackPanel">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1, AncestorType={x:Type RadioButton}}, Path=IsChecked}"
Value="True">
<Setter Property="Background" Value="Thistle" />
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
I've to change the Text property of a combo box when IsEnabled sets to false and it can manually selects field from the items source when IsEnabled is true from the same control, is this possible?
XAML:
<ComboBox Name="cmbIntervals"
Grid.Row="5"
Grid.Column="1"
Width="150"
HorizontalAlignment="Left"
VerticalAlignment="Top"
IsEnabled="{Binding ElementName=chkBox,
Path=IsChecked}"
ItemsSource="{Binding Source={x:Static res:Parameters.Instance},
Path=Intervals}"
Text="{Binding [Intervals], Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}" >
<ComboBox.Style>
<Style TargetType="{x:Type ComboBox}">
<Style.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Text" Value="1"/>
</Trigger>
</Style.Triggers>
</Style>
</ComboBox.Style>
</ComboBox>
Just check in ViewModel
if(!IsChecked)
{
TextProperty="1"; //Propery to bind to ComboBox Text
}
I know that a passwordbox in wpf could not use the Validation.ErrorTemplate, anyhow i have to show the user, that something is wrong.
My Passwordbox has a binding like this
<PasswordBox Name="Password" local:PasswordHelper.Text="{Binding PasswordProp, Mode=TwoWay}" />
Is it possible to get the same style like the default errortemplate (red border) for this passwordbox, if something is wrong?
This is my ErrorTemplate that I use for the other controls
<Style x:Key="baseControlStyle">
<Setter Property="Control.FontFamily" Value="Verdana" />
<Setter Property="Control.FontSize" Value="12" />
<Setter Property="ToolTipService.ShowOnDisabled" Value="True" />
<Setter Property="Validation.ErrorTemplate" >
<Setter.Value>
<ControlTemplate>
<DockPanel LastChildFill="True">
<Image x:Name="Bild"
DockPanel.Dock="Right"
Source="../Resources/Nein.ico"
Margin="-5 0 0 0"
MaxHeight="16"
MaxWidth="16"
VerticalAlignment="Center"
ToolTip="{Binding ElementName=myControl, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}">
</Image>
<Border BorderBrush="Red" BorderThickness="1" CornerRadius="2">
<AdornedElementPlaceholder x:Name="myControl" />
</Border>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="Control.ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}"/>
</Trigger>
</Style.Triggers>
</Style>
Thanks
One solution would be to put an actual TextBox underneath the PasswordBox and bind the Text property to PasswordProp too and give the TextBox the ErrorTemplate:
<Grid>
<TextBox Template="{x:Null}" Style="{StaticResource baseControlStyle}" Text="{Binding PasswordProp, Mode=TwoWay}" />
<PasswordBox Name="Password" local:PasswordHelper.Text="{Binding PasswordProp, Mode=TwoWay}" />
</Grid>
Since the controls of the ErrorTemplate will be put on an adorner layer, your error template will be displayed on top of the PasswordBox event though the TextBox is underneath the PasswordBox.
Also note that I have set the TextBox controltemplate to null. Since it is not supposed to be visible it doesn't need to be rendered.
I have a listbox where the itemtemplate is using a style. The styles specifies a border with a datatrigger setting the visibility of the border to collapsed depending on a property. This works fine except I can still see a very narrow line for each item, in the list, that is collapsed. I was hoping someone could help with how to set the visibility so that there are no visible traces as this is quite apparent when consecutive items have been collapsed.
The datatemplate specifies an outer border with a dockpanel inside of this - there are then stackpanels docked to this.
Any help is appreciated.
Well this is a simplified template:
<DataTemplate x:Key="myTemplate">
<Border BorderThickness="0">
<Border.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsActive}" Value="False">
<Setter Property="Border.Visibility" Value="Collapsed" />
</DataTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<DockPanel LastChildFill="True" HorizontalAlignment="Stretch">
<StackPanel DockPanel.Dock="Right" HorizontalAlignment="Right" >
<TextBlock Text="{Binding Path=SeqNo, Converter={StaticResource SeqToTextConv}}"/>
<Label Content="..." />
</StackPanel>
</DockPanel>
</Border>
</DataTemplate>
You are succesfully hiding your item, however, the ListBox wraps each of your items within a ListBoxItem, this adds concepts such as selection to your item. I suspect you are still seeing the ListBoxItem in the case where your items are hidden. You can use the ItemContainerStyle to hide ListBoxItems ...
<ListBox>
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsActive}" Value="False">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
This can also be achieved by populating ListBox.Items only with ListBoxItem instead of other controls:
ListBox.Items.Add(new ListBoxItem {
Content = new CheckBox {Content = "item 1"}
})
or
<ListBox>
<ListBox.Items>
<ListBoxItem>
<CheckBox Content="item 1"/>
</ListBoxItem>
</ListBox.Items>
</ListBox>
Then in the code behind or in the trigger, you can hide the items directly:
ListBox.Items[0].Visibility = Visibility.Collapse
This will hide the item as well as the 4px border. This method gives you control of visibility for each individual item.
I went with ColinE's proposed solution. Here is a full snipped for everybody's convenience. Thanks ColienE.
<ListBox ItemsSource="{Binding Properties}" Height="110">
<ListBox.ItemTemplate>
<HierarchicalDataTemplate>
<CheckBox Content="{Binding Name}" IsChecked="{Binding IsSelected}" Visibility="{Binding Visible}" />
</HierarchicalDataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Style.Triggers>
<DataTrigger Binding="{Binding Visible}" Value="Collapsed">
<Setter Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
Why is there no tooltip text on errors?
<Style TargetType="{x:Type TextBox}">
<Setter Property="Validation.ErrorTemplate">
<Setter.Value>
<ControlTemplate>
<StackPanel>
<Border ...>
<AdornedElementPlaceholder ...
ToolTip="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}" />
</Border>
...
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I also noticed that
<AdornedElementPlaceholder ...
ToolTip="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}" />
fails but the below suceeds, even with the same binding, why is this so? Doesn't AdornedElementPlaceholder refer to the text box? Even if it doesn't, shouldn't a tooltip appear somewhere?
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}" />
</Trigger>
</Style.Triggers>
I know I'm late, but let me share a solution I found studying this question: WPF custom validator with tooltip.
In it's simplest form this ErrorTemplate shows only a Tooltip with the ErrorContent for the whole AdornedElement.
<ControlTemplate x:Key="validationTemplate">
<Grid Background="Transparent"
ToolTip="{Binding Path=/ErrorContent}">
<AdornedElementPlaceholder />
</Grid>
</ControlTemplate>
But of course you can decorate it as desired e.g. with a Tooltip for just a marker.
<ControlTemplate x:Key="validationTemplate">
<Grid>
<Ellipse Fill="Red" Opacity="0.8" Width="10" Height="10"
HorizontalAlignment="Right" VerticalAlignment="Top"
ToolTip="{Binding Path=/ErrorContent}" />
<AdornedElementPlaceholder />
</Grid>
</ControlTemplate>
Put this Template in Resources and all you have to do is setting the Validation.ErrorTemplate.
Validation.ErrorTemplate="{StaticResource validationTemplate}"
Even this annoying Trigger is no longer needed.
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}" />
</Trigger>
</Style.Triggers>
You can't place a tooltip on the AdornedElementPlaceholder, I don't think it's visible at all, it's just reserving space for whoever uses it (in your case a TextBox). Looking at the Visual Tree with Snoop we can see that the TemplatedAdorner ends up in a different place in the VisualTree than the TextBox so there will be now way for us to find the TextBox from the VisualTree. We can find it through AdornedElement, but we still won't be able to set a tooltip.
The only thing visible here in the TemplatedAdorner is the Border. The Border knows its Child - the TemplatedAdorner - which in turn knows its AdornedElement - the TextBox. So we could set the ToolTip for the Border with this. (However, this Binding seems to fail to update the Tooltip for the Border. It works when I look at it with Snoop and after that it displays.)
<Border BorderBrush="Red"
BorderThickness="4"
ToolTip="{Binding RelativeSource={RelativeSource self},
Path=Child.AdornedElement.(Validation.Errors)[0].ErrorContent}">
So, the TextBox has its AttachedProperty Validation where we can find the ErrorContent so it must set its own ToolTip like you did at your last example, otherwise it won't work.
I found a way to implement ToolTip with the returned error message from the validation class that you might create to validate your input.
First: Binding the error message
Adding <Style> for the TextBox with Style.Trigger as followed:
<Style TargetType="{x:Type TextBox}" x:Key="ToolTipError">
<!-- Some style setters -->
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="true">
<Setter Property="ToolTip" Value="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=(Validation.Errors)[0].ErrorContent}"/>
</Trigger>
</Style.Triggers>
</Style>
Second: Add the style to TextBox
<TextBox
Style="{StaticResource ToolTipError}"
Validation.ErrorTemplate="{StaticResource validationTemplate}">
<TextBox.Text>
<Binding
Path="YourViewModelProperty"
UpdateSourceTrigger="PropertyChanged"
ValidatesOnNotifyDataErrors="True"
ValidatesOnDataErrors="True"
NotifyOnValidationError="True">
<Binding.ValidationRules>
<ExceptionValidationRule:DateValidationRule ValidatesOnTargetUpdated="True"/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
Bonus!
You can change the ugly red border with other thing.
For example you can change it to red exclamation mark:
<Window.Resources>
<ControlTemplate x:Key="validationTemplate">
<StackPanel>
<TextBlock Text="!" FontSize="26" Foreground="Red"/>
<AdornedElementPlaceholder/>
</StackPanel>
</ControlTemplate>
<Window.Resources>