Hi all I am new to WPF, I have used a list view to render as grid view. I have a image column for which I set a value by binding the path. Now the problem is I need to change the path of the image based on a condition. If the condition is true I need the path of the image to be different. If false I change it to another path. Can this be done row by row? Below is my listview. Please Help
<ListView Name="LstGrd" Margin="0,105,0,138">
<ListView.View>
<GridView >
<GridViewColumn Header=" Name" Width="120" DisplayMemberBinding="{Binding Path=Name}" />
<GridViewColumn Header=" Address" Width="250" DisplayMemberBinding="{Binding Path=Address}" />
<GridViewColumn Header=" City" Width="50" DisplayMemberBinding="{Binding Path=City}" />
<GridViewColumn Header=" State" Width="75" DisplayMemberBinding="{Binding Path=State}" />
<GridViewColumn Header=" PostalCode" Width="75" DisplayMemberBinding="{Binding Path=PostalCode}" />
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Width="16" Name="Test" Height="16" Source="{Binding Path=ImagePath,Mode=TwoWay}"/>
<TextBlock Text="Status"/>
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
If I understand your issue properly, you want to change the image if some condition changes. I created a dummy version of the class you are binding to your listview, and added a property called "IsSelected" to show this.
<ListView Name="LstGrd" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<ListView.View>
<GridView >
<GridViewColumn Header="">
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsSelected}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header=" Name" Width="120" DisplayMemberBinding="{Binding Path=Name}" />
<GridViewColumn Header=" Address" Width="250" DisplayMemberBinding="{Binding Path=Address}" />
<GridViewColumn Header=" City" Width="50" DisplayMemberBinding="{Binding Path=City}" />
<GridViewColumn Header=" State" Width="75" DisplayMemberBinding="{Binding Path=State}" />
<GridViewColumn Header=" PostalCode" Width="75" DisplayMemberBinding="{Binding Path=PostalCode}" />
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Width="16" Name="Test" Height="16" Source="{Binding Path=ImagePath,Mode=TwoWay}"/>
<TextBlock Text="Status"/>
</StackPanel>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding IsChecked}" Value="True">
<Setter Property="Source" Value="{Binding Path=ImagePath2}" TargetName="Test" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
The thing to notice here is that I added a column (this is optional - I just did so to make it easier to demonstrate). Then, in your Image column, you need to add a DataTrigger to your DataTemplate to handle that property change.
Here is just the DataTemplate:
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Width="16" Name="Test" Height="16" Source="{Binding Path=ImagePath,Mode=TwoWay}"/>
<TextBlock Text="Status"/>
</StackPanel>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding IsChecked}" Value="True">
<Setter Property="Source"
Value="{Binding Path=ImagePath2}"
TargetName="Test" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
This has the advantage over a Converter because it is a XAML only implementation.
You should use a converter:
<Image Source="{Binding Path = ImagePath, Mode = TwoWay, Converter={StaticResource imageToValidatedImageConv}}" />
Where imageToValidatedImageConv is a resource defined as: <local:ImageToValidatedImageConverter x:Key="imageToValidatedImageConv" />
and your converter a class like:
public class ImageToValidatedImageConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if()
{
//return image1
}
else
{
//return image2
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new Exception("Cant convert back");
}
}
Related
To preface the bulk of the question, I've found several answers regarding CellTemplate and DataTemplate, as well as one setting HeaderContainerStyle, and none of them worked; results ranged from no change to a crash.
I'm trying to change the color of the first entry in each column for my listview (basically so the header for each column sticks out). Here's the most recent thing I've tried with no success. Any suggestions or advice are greatly appreciated.
<ListView Height="380" VerticalAlignment="Top" HorizontalContentAlignment="Stretch">
<ListView.View>
<GridView>
<GridViewColumn Header="First" Width="60" >
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock x:Name="Txt" Text="{Binding First}" Background="DarkBlue"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Last" Width="60" DisplayMemberBinding="{Binding Last}" />
<GridViewColumn Header="Group" Width="80" DisplayMemberBinding="{Binding Group}" />
</GridView>
</ListView.View>
</ListView>
Is the following code what you are looking for?
For the first row:
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock x:Name="Txt" Text="{Binding First}"/>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource PreviousData}}" Value="{x:Null}">
<Setter TargetName="Txt" Property="Background" Value="DarkBlue"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</GridViewColumn.CellTemplate>
For the header:
<GridViewColumn Header="First" Width="60" >
<GridViewColumn.HeaderContainerStyle>
<Style TargetType="{x:Type GridViewColumnHeader}">
<Setter Property="Background" Value="LightSkyBlue"/>
</Style>
</GridViewColumn.HeaderContainerStyle>
</GridViewColumn>
I'm trying to save record when combination of keys pressed Ctrl + S.
Below code works fine only when i exit TextBox and select line then press Ctrl + S.
How to SelectItem without exiting TextBox? For example: typing text >> Ctrl + S >> continue typing.
Here is my code:
if (Keyboard.IsKeyDown(Key.LeftCtrl) && Keyboard.IsKeyDown(Key.S))
{
sql.saveSoftwareChanges(_list.SelectedItem as Software);
e.Handled = true;
}
and XAML:
<ListView x:Name="_list" Visibility="Visible" KeyDown="_list_KeyDown">
<!--RESOURCES-->
<ListView.Resources>
<Style TargetType="ListViewItem">
<Style.Triggers>
<Trigger Property="IsKeyboardFocusWithin" Value="true">
<Setter Property="IsSelected" Value="true" />
</Trigger>
<Trigger Property="IsSelected" Value="true">
<Setter Property="Background" Value="#FFFFFF9A" />
</Trigger>
</Style.Triggers>
</Style>
</ListView.Resources>
<!--/RESOURCES-->
<ListView.View>
<GridView>
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<Button x:Name="_save" Content="Save" MinWidth="20" Width="AUTO" Click="_save_Click" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Product ID">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding productId}" MinWidth="20" Width="AUTO" Padding="2"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Product">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding product}" MinWidth="20" Width="AUTO" Padding="2"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Path">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding path}" MinWidth="20" Width="AUTO" Padding="2"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Master Path">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding master_path}" MinWidth="20" Width="AUTO" Padding="2"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Parameters">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding parameters}" MinWidth="20" Width="AUTO" Padding="2"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Windows Version">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding windowsVersion}" MinWidth="20" Width="AUTO" Padding="2"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
After a lot of research and trial and error I've got the solution.
It's as simple as moving out of that field, which can be achieved by:
MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
and entire method looks like:
if (Keyboard.IsKeyDown(Key.LeftCtrl) && Keyboard.IsKeyDown(Key.S))
{
var uie = e.OriginalSource as UIElement;
uie.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
sql.saveSoftwareChanges(_list.SelectedItem as Software);
uie.Focus();
e.Handled = true;
}
I hope that will help others as well.
You have to place your save code in a function then call this function from any control that may have the focus at that time. (i.e. the text box as well).
Remember that keyboard events only fire when the corresponding control has focus.
Test this:
<ListView x:Name="_list" Visibility="Visible" KeyDown="_list_KeyDown">
<!--RESOURCES-->
<ListView.Resources>
<Style TargetType="ListViewItem">
<Style.Triggers>
<Trigger Property="IsKeyboardFocusWithin" Value="true">
<Setter Property="IsSelected" Value="true" />
</Trigger>
<Trigger Property="IsSelected" Value="true">
<Setter Property="Background" Value="#FFFFFF9A" />
</Trigger>
</Style.Triggers>
</Style>
</ListView.Resources>
<!--/RESOURCES-->
<ListView.View>
<GridView>
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<Button x:Name="_save" Content="Save" MinWidth="20" Width="AUTO" Click="_save_Click" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Product ID">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding productId}" MinWidth="20" Width="AUTO" Padding="2" KeyDown="_list_KeyDown"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Product">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding product}" MinWidth="20" Width="AUTO" Padding="2" KeyDown="_list_KeyDown"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Path">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding path}" MinWidth="20" Width="AUTO" Padding="2" KeyDown="_list_KeyDown"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Master Path">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding master_path}" MinWidth="20" Width="AUTO" Padding="2" KeyDown="_list_KeyDown"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Parameters">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding parameters}" MinWidth="20" Width="AUTO" Padding="2" KeyDown="_list_KeyDown"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Windows Version">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding windowsVersion}" MinWidth="20" Width="AUTO" Padding="2" KeyDown="_list_KeyDown"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
How to create Check box for Column inside Listview. i was able to make checkbox for listview items. but i want to have checkbox for Column itself.like in windows:
here is code in XAML
<ListView HorizontalAlignment="Left" Grid.Row="1" Width="400">
<ListView.View>
<GridView>
<GridViewColumn Width="140" Header="Column1 With Checkbox">
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox Tag="{Binding}" IsThreeState="False" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Width="140" Header="Column2" />
<GridViewColumn Width="115" Header="Column3" />
</GridView>
</ListView.View>
</ListView>
Note that this will only make checkboxes for items not Column itself. so how to make this happen?
You can make the header a custom control by defining it under the GridViewColumn.Header property.
<ListView HorizontalAlignment="Left" Grid.Row="1" Width="400">
<ListView.View>
<GridView>
<GridViewColumn Width="140">
<GridViewColumn.Header>
<StackPanel Orientation="Horizontal">
<Checkbox IsChecked="{Binding YourCheckedProperty}" />
<TextBlock Text="Column1" />
</StackPanel>
<GridViewColumn.Header>
</GridViewColumn>
<GridViewColumn Width="140" Header="Column2" />
<GridViewColumn Width="115" Header="Column3" />
</GridView>
</ListView.View>
</ListView>
I am having a listview and using view as gridview as follows:
<ListView Grid.Row="1" Grid.Column="0" Height="100" HorizontalAlignment="Left" Margin="10,10,10,10" Name="listView2" VerticalAlignment="Top" Width="300" ItemsSource="{Binding}" SelectionChanged="listView2_SelectionChanged" SelectionMode="Multiple">
<ListView.View>
<GridView AllowsColumnReorder="True">
<GridViewColumn Header="Select">
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn DisplayMemberBinding="{Binding Path=FirstName}" Header="First Name" Width="100"/>
<GridViewColumn DisplayMemberBinding="{Binding Path=LastName}" Header="Last Name" Width="100"/>
</GridView>
</ListView.View>
</ListView>
Now the issue is that when the user will check on the checkbox the record should get selected. Also is the user selects the record from the list then the corresponding checkboxes should be selected.
How to do it ?
I'm assuming that your view model has IsSelected property:
public Boolean IsSelected
{
get { return isSelected; }
set
{
if (isSelected != value)
{
isSelected = value;
OnPropertyChanged("IsSelected");
}
}
}
private Boolean isSelected;
So, let's change markup:
<ListView ItemsSource="{Binding}" SelectionMode="Multiple">
<!-- add style for the item in list view: -->
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"/>
</Style>
</ListView.ItemContainerStyle>
<ListView.View>
<GridView AllowsColumnReorder="True">
<GridViewColumn Header="Select">
<GridViewColumn.CellTemplate>
<DataTemplate>
<!-- bind the checkbox to the IsSelected property: -->
<CheckBox IsChecked="{Binding IsSelected, Mode=TwoWay}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn DisplayMemberBinding="{Binding Name}" Header="Name" Width="100"/>
</GridView>
</ListView.View>
</ListView>
The simplest ways:
<GridViewColumn Header="None">
<GridViewColumn.CellTemplate>
<DataTemplate>
<CheckBox Width="50"
Height="50"
IsChecked="{Binding RelativeSource={RelativeSource AncestorType={x:Type ListViewItem}},
Path=IsSelected,Mode=TwoWay}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
I wrote XAML as follows:
<UserControl.Resources>
<GridViewColumnCollection x:Key="gvcc">
<GridViewColumn Header="Klient"
DisplayMemberBinding="{Binding CustomerName}"
Width="80">
</GridViewColumn>
<GridViewColumn Header="Budżet"
DisplayMemberBinding="{Binding Budget, StringFormat={}{0:C}}"
Width="80">
</GridViewColumn>
<GridViewColumn Header="Zysk. zakł."
DisplayMemberBinding="{Binding ExpectedProfability, StringFormat={}{0:C}}"
Width="80">
</GridViewColumn>
<GridViewColumn Header="Zysk. real."
DisplayMemberBinding="{Binding RealProfability, StringFormat={}{0:C}}"
Width="80">
</GridViewColumn>
<GridViewColumn Header="Miejsce"
DisplayMemberBinding="{Binding Place}"
Width="80" />
<GridViewColumn Header="Nr proj."
DisplayMemberBinding="{Binding Number}"
Width="80">
</GridViewColumn>
</GridViewColumnCollection>
</UserControl.Resources>
...
<Grid>
<ScrollViewer ScrollViewer.VerticalScrollBarVisibility="Visible">
<ItemsControl ItemsSource="{Binding GroupedProjects}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="70" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Border Grid.Column="0" Grid.Row="0" Grid.RowSpan="3" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Background="Red" >
<TextBlock FontSize="13" Text="{Binding Month}" TextAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center" />
</Border>
<GridViewHeaderRowPresenter Name="hrp" Columns="{StaticResource gvcc}" Grid.Column="1" Grid.Row="0" />
<ListBox ItemsSource="{Binding Details}" Grid.Column="1" Grid.Row="1" ScrollViewer.VerticalScrollBarVisibility="Disabled"
GotFocus="ListBox_GotFocus"
PreviewMouseWheel="ListBox_PreviewMouseWheel"
SelectedItem="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.SelectedProject}">
<ListBox.ItemTemplate>
<DataTemplate>
<GridViewRowPresenter Columns="{StaticResource gvcc}" Height="24" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<!-- HERE IS THE PROBLEM -->
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</ScrollViewer>
</Grid>
Data are grouped in the ListBox, underneath the ListBox I want to display something like a summary row. I wanted to do this row as the StackPanel with TextBlock controls. The problem is - how to relate the width of the TextBox controls with the widths of columns in the ListBox.
Let's say the "summary row" is something like that:
<StackPanel Orientation="Horizontal">
<TextBlock Width="bind to ListBox.Column1.Width + ListBox.Column2.Width">some data</TextBlock>
<TextBlock Width="bind to ListBox.Column3.Width">other data</TextBlock>
<TextBlock Width="bind to ListBox.Column4.Width">etc.</TextBlock>
</StackPanel>
As you can see - first TextBlock width is something like "ColumnSpan = 2". The width of the other TextBlocks is simply the width of a column to which I would like to pair them.
Is such a thing is even possible in XAML? Can anyone of you knows how to implement a similar solution in different way?
If you are doing this through MVVM, you can easily use property binding to get it done. Just set the width of each of the ListBox columns to properties in your ViewModel. The textBox controls widths will be bound to a seperate readonly property which takes the appropriate widths, manipulates them in some way, and returns a value. You will have to implement INotifyPropertyChanged and call it on each of the textbox width properties every time a listboxwidth property is changed.
So something like so:
Private _Column1Width As Double
Public Property Column1Width() As Double
Get
Return _Column1Width
End Get
Set(ByVal value As Double)
_Column1Width = value
OnPropertyChanged("TextBox1Width")
End Set
End Property
Private _Column2Width As Double
Public Property Column2Width() As Double
Get
Return _Column2Width
End Get
Set(ByVal value As Double)
_Column2Width = value
OnPropertyChanged("TextBox1Width")
End Set
End Property
Public ReadOnly Property TextBox1Width() As Double
Get
Return Column1Width + (Column2Width * 2)
End Get
End Property
And bindings like so:
<GridViewColumnCollection x:Key="gvcc">
<GridViewColumn Header="Klient"
DisplayMemberBinding="{Binding CustomerName}"
Width="{Binding Column1Width, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"}">
</GridViewColumn>
<GridViewColumn Header="Budżet"
DisplayMemberBinding="{Binding Budget, StringFormat={}{0:C}}"
Width="{Binding Column2Width, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
</GridViewColumn>
<GridViewColumn Header="Zysk. zakł."
DisplayMemberBinding="{Binding ExpectedProfability, StringFormat={}{0:C}}"
Width="80">
</GridViewColumn>
<GridViewColumn Header="Zysk. real."
DisplayMemberBinding="{Binding RealProfability, StringFormat={}{0:C}}"
Width="80">
</GridViewColumn>
<GridViewColumn Header="Miejsce"
DisplayMemberBinding="{Binding Place}"
Width="80" />
<GridViewColumn Header="Nr proj."
DisplayMemberBinding="{Binding Number}"
Width="80">
</GridViewColumn>
</GridViewColumnCollection>
<TextBlock Width="{Binding TextBox1Width}">some data</TextBlock>
Everything resizes just as it should continuously updating as you resize the columns.