Problem: WPF Checkbox inside Listbox is disabled but still clickable - wpf

I have a Style for a listbox, using checkboxes. I want to bind the isEnabled property of each checkbox to a property (ItemEnabled) of each item. This is my code:
<Setter Property="ItemContainerStyle">
<Setter.Value>
<Style TargetType="{x:Type ListBoxItem}" >
<Setter Property="Margin" Value="2" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<CheckBox Focusable="False"
IsChecked="{Binding Path=IsSelected, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent} }"
IsEnabled="{Binding Path=ItemEnabled, Mode=OneWay}">
<ContentPresenter></ContentPresenter>
</CheckBox>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Setter.Value>
</Setter>
So far, the checkboxes which have the property ItemEnabled set to false, are grayed out. However, still clickable and checkable/uncheckable.
Any ideas?

If I understand your question correctly, you want to control the checkbox 'IsEnabled' controlled via model, 'IsChecked' controlled by selection of listview selection.
You can do by simply creating DataTemplate for your model
<DataTemplate DataType="{x:Type local:TestModel}">
<StackPanel Orientation="Horizontal">
<CheckBox IsEnabled="{Binding ItemEnabled}"
IsChecked="{Binding RelativeSource={RelativeSource AncestorType=ListViewItem},Path=IsSelected}"
></CheckBox>
<TextBlock Text="{Binding Name}"></TextBlock>
</StackPanel>
</DataTemplate>
TestModel:
public class Emp
{
public int ID { get; set; }
public string Name { get; set; }
public bool ItemEnabled { get; set; }
}
Remove the 'ItemContainerStyle' from your code.
Hope this helps.

Thanks, RajN.
I managed to solve it based on your comment.
Here is the new XAML:
<Setter Property="ItemContainerStyle">
<Setter.Value>
<Style TargetType="{x:Type ListBoxItem}" >
<Setter Property="Margin" Value="2" />
<Setter Property="Focusable" Value="False" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<ContentPresenter></ContentPresenter>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<CheckBox Focusable="False"
IsChecked="{Binding Path=IsSelected, Mode=TwoWay, RelativeSource={RelativeSource AncestorType=ListBoxItem} }"
IsEnabled="{Binding Path=ItemEnabled, Mode=OneWay}"
Content="{Binding Path=ItemName, Mode=OneWay}">
</CheckBox>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</Setter.Value>
</Setter>

Related

Changing background color for a ComboBox, it's not changing color at all

I going crazy that I just can't change the color of the ComboBox. Have tried to use the background property right on the ComboBox but nothing happens.
Have also tried to use a Style block and set the background color, but that does also not work.
Code
<ComboBox Padding="7" Height="34" Background="#ffffff">
<ComboBox.Resources>
<Style x:Key="{x:Type ComboBox}" TargetType="ComboBox">
<Setter Property="Background" Value="red" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="BorderBrush" Value="black" />
</Style>
</ComboBox.Resources>
<ComboBoxItem IsSelected="True">1 - Room</ComboBoxItem>
<ComboBoxItem>2 - Rooms</ComboBoxItem>
<ComboBoxItem>3 - Rooms</ComboBoxItem>
<ComboBoxItem>4 - Rooms</ComboBoxItem>
<ComboBoxItem>5+ - Rooms</ComboBoxItem>
</ComboBox>
Even though that I have set the background color to white, It still only the standard grey color.
Here you can see how it looks:
Hope someone can tell me what I'm doing wrong?
here are several thing which in my opinion can help you:
Remove the Background definition from the ComboBox declaration(Background="#ffffff").
Move the combo items declaration to the combo holding Grid because of the fact that ItemTemplate and ItemTemplateSelector are ignored for items already of the ItemsControl's container.
Implement the data template selector to support data templates of combo (one for selected item, second for the items to select).
Here is the XAML code
<Grid>
<Grid.Resources>
<x:Array Type="{x:Type system:String}" x:Key="MyRoomsArray">
<system:String>1 - Room</system:String>
<system:String>2 - Rooms</system:String>
<system:String>3 - Rooms</system:String>
<system:String>4 - Rooms</system:String>
<system:String>5+ - Rooms</system:String>
</x:Array>
</Grid.Resources>
<ComboBox Padding="7" Height="34" SelectedIndex="0" ItemsSource="{StaticResource MyRoomsArray}">
<ComboBox.Resources>
<DataTemplate x:Key="ItemToSelect">
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Border HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Background="Red"
BorderBrush="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ComboBox}, Path=BorderBrush, UpdateSourceTrigger=PropertyChanged}"
BorderThickness ="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ComboBox}, Path=BorderThickness, UpdateSourceTrigger=PropertyChanged}">
<TextBlock HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Text="{Binding }" />
</Border>
</Grid>
</DataTemplate>
<DataTemplate x:Key="SelectedItem">
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Border HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Background="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ComboBox}, Path=Background, UpdateSourceTrigger=PropertyChanged}"
BorderBrush="Transparent"
BorderThickness ="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ComboBox}, Path=BorderThickness, UpdateSourceTrigger=PropertyChanged}">
<TextBlock HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Text="{Binding }" />
</Border>
</Grid>
</DataTemplate>
<wpfComboBAckground:ComboDataTemplateSelector x:Key="ComboDataTemplateSelector" Selected="{StaticResource SelectedItem}" ItemToSelect="{StaticResource ItemToSelect}"/>
<Style TargetType="ComboBox">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="Background" Value="Red" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="BorderBrush" Value="Black" />
<Setter Property="ItemTemplateSelector" Value="{StaticResource ComboDataTemplateSelector}"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Transparent"></Setter>
</Trigger>
<Trigger Property="IsMouseOver" Value="False">
<Setter Property="Background" Value="Red"></Setter>
</Trigger>
</Style.Triggers>
</Style>
</ComboBox.Resources>
</ComboBox>
</Grid>
Here is the data template selector
public class ComboDataTemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
var selected = false;
// container is the ContentPresenter
FrameworkElement fe = container as FrameworkElement;
if (fe == null) return ItemToSelect;
var cbo = fe.TemplatedParent as ComboBox;
if (cbo != null)
selected = true;
return selected ? Selected : ItemToSelect;
}
public DataTemplate Selected { get; set; }
public DataTemplate ItemToSelect { get; set; }
}
How it looks like:
Regards.

Merge Style.Triggers with property Template in WPF

I want to set a style for my DataGrid, but I do not know where is the problem
the backgroud property does not work with its value in the presence of the Template property.
my code:
<Style x:Key="DataGridStyle1" TargetType="{x:Type DataGrid}">
<Setter Property="CellStyle" Value="{DynamicResource GridStyle1}"/>
</Style>
<Style x:Key="GridStyle1" TargetType="DataGridCell">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True" >
<Setter Property="Background" Value="SeaGreen"/>
</Trigger>
</Style.Triggers>
<Style.Setters>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridCell}">
<Border Name="DataGridCellBorder">
<ContentControl Content="{TemplateBinding Content}">
<ContentControl.ContentTemplate>
<DataTemplate>
<TextBlock Background="Transparent" TextWrapping="WrapWithOverflow" TextTrimming="CharacterEllipsis"
Height="auto" Width="auto" Text="{Binding Text}"/>
</DataTemplate>
</ContentControl.ContentTemplate>
</ContentControl>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style.Setters>
</Style>
Help me please.
You have explicitly set TextBlock background to Transparent, so it won't pick value from DataGridCell. You should bind with background of DataGridCell using RelativeSource like this:
<TextBlock Background="{Binding Background, RelativeSource={RelativeSource
Mode=FindAncestor, AncestorType=DataGridCell}}"
TextWrapping="WrapWithOverflow" TextTrimming="CharacterEllipsis"
Height="auto" Width="auto" Text="{Binding Text}"/>

BInding issues with showing Image in xamDataGrid

I want to show an image in one field of XamDataGrid.
The path of the Image I have is a property in my Model. I was able to Show the image using normal WPF DataGrid, but facing issues with XamDataGrid.( see in point 2)
Binding ItemImage Property to XamDataGrid Field.
<igDP:Field.Settings>
<igDP:FieldSettings AllowEdit="False">
<igDP:FieldSettings.CellValuePresenterStyle>
<Style TargetType="{x:Type igDP:CellValuePresenter}" >
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type igDP:CellValuePresenter}">
<Grid>
<Image
Source="{Binding RelativeSource={RelativeSource AncestorType= {x:Type igDP:XamDataGrid}}, Path=ItemImage, Converter={StaticResource ImageConverter}}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</igDP:FieldSettings.CellValuePresenterStyle>
</igDP:FieldSettings>
</igDP:Field.Settings>
`
Working with normal WPF Data Grid.
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Image Source="{Binding ItemImage, Converter={StaticResource ImageConverter}}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
please let me know. if i have to make any change in Step 1.
The DataContext of each field in xamDataGrid is DataRecord object, The property DataItem in it contains your object, so the binding should be defined like so:
<igDP:Field.Settings>
<igDP:FieldSettings AllowEdit="False">
<igDP:FieldSettings.CellValuePresenterStyle>
<Style TargetType="{x:Type igDP:CellValuePresenter}" >
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type igDP:CellValuePresenter}">
<Grid>
<Image
Source="{Binding DataItem.ItemImage, Converter={StaticResource ImageConverter}}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</igDP:FieldSettings.CellValuePresenterStyle>
</igDP:FieldSettings>

Unable to command bind toggle button as control template

Here is the code :
<Window.DataContext>
<local:MainWindowViewModel />
</Window.DataContext>
<Window.Resources>
<Style x:Key="RadioToggleButtonStyle" TargetType="RadioButton">
<Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RadioButton}">
<ToggleButton Content="{Binding Content, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" IsChecked="{Binding IsChecked, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" />
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Width" Value="150" />
<Setter Property="Height" Value="25" />
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
</Window.Resources>
<Grid>
<RadioButton Name="radioButton1"
Height="29"
Margin="193,195,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Top"
**Command="{Binding Path=RadioClickCommand}"**
Content="RadioButton"
Style="{StaticResource RadioToggleButtonStyle}" />
</Grid>
In MainWindowViewModel : I have following command registration
public ICommand RadioClickCommand
{
get { return new RelayCommand(RadioClickExecute); }
}
private void RadioClickExecute()
{
}
Button click never triggers the command bind.
any help would be appreciated.
You forgot in your style that you have to define a Command of a ToggleButton
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RadioButton}">
<ToggleButton Content="{Binding Content, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" IsChecked="{Binding IsChecked, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"
Command="{Binding Command, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}"/>
</ControlTemplate>
</Setter.Value>
</Setter>

Using styles within a data template

I have a class called item, and it contains just two properties. I will display them on the screen as buttons with a style. This question relates to how I can style the button based on the IsSelected value, when the element I want to affect is in the style not the data template. I have already tried with a Trigger but been unable to get it to work.
The class is below.
public class Item : ObservableObject
{
private string _title;
private bool _isSelected;
public string Title
{
get { return _title; }
set
{
_title = value;
RaisePropertyChanged("Title");
}
}
public bool IsSelected
{
get { return _isSelected; }
set
{
_isSelected = value;
RaisePropertyChanged("IsSelected");
}
}
}
I use a data template to display these items in a ItemsControls.
<ItemsControl ItemsSource="{Binding Path=Items}" ItemTemplate="{StaticResource ResourceKey=ItemTemplate}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
Using the following style and data template.
<Style x:Key="ItemButton" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Name="ButtonBorder" BorderThickness="2,2,2,0" BorderBrush="#AAAAAA" CornerRadius="6,6,0,0" Margin="2,20,0,0" Background="Black">
<ContentPresenter
VerticalAlignment="Center"
HorizontalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<DataTemplate x:Key="ItemTemplate">
<Button Height="60" Style="{StaticResource ItemButton}" Name="Button">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Title}"
HorizontalAlignment="Left" Margin="5,5,5,3" FontSize="25" Foreground="#6B6B6B" FontFamily="Arial" />
<Button Style="{StaticResource NoChromeButton}" Margin="0,0,5,0">
<Button.Content>
<Image Height="20" Source="/WpfApplication1;component/Image/dialogCloseButton.png"></Image>
</Button.Content>
<Button.ToolTip>
Close
</Button.ToolTip>
</Button>
</StackPanel>
</Button>
</DataTemplate>
I need to change the Background of "ButtonBorder" from Black to White when IsSelected is True, on the object Item.
I have added in a Trigger in the Data Template
This does not work, I guess its because the style overrides the DataTemplate, thus the background stays white. Yet when i try to do a trigger in the style, I can't access the property IsSelected?
DataTemplate Trigger
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding IsSelected}" Value="True">
<Setter TargetName="Button" Property="Background" Value="White"/>
</DataTrigger>
</DataTemplate.Triggers>
Style trigger
<Style.Triggers>
<DataTrigger Binding="{Binding IsSelected}" Value="True">
<Setter Property="Background" Value="White"/>
</DataTrigger>
</Style.Triggers>
Am i missing something?
Make your ButtonBorder.Background be {TemplateBinding Background}, which means it will use whatever background color is assigned to the templated Button, then you can change your Button's background based on a Trigger
<Style x:Key="ItemButton" TargetType="Button">
<Setter Property="Background" Value="Black" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Name="ButtonBorder" Background="{TemplateBinding Background}" ... >
<ContentPresenter ... "/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="SelectableItemButton" TargetType="Button" BasedOn="{StaticResource ItemButton}">
<Setter Property="Background" Value="Black" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsSelected}" Value="True">
<Setter Property="Background" Value="White"/>
</DataTrigger>
</Style.Triggers>
</Style>
<DataTemplate x:Key="ItemTemplate">
<Button Height="60" Style="{StaticResource SelectableItemButton}">
...
</Button>
</DataTemplate>
I'm also making a SelectableItemButton Style which inherits from ItemButton, and just implements the trigger
Shouldn't the target be "ButtonBorder" instead of "Button" in :
<Setter TargetName="Button"....
Also, to access the property IsSelected you need to set the TargetType in the style ....

Resources