I have the following ListView:
<ListView>
<ListView.View>
<GridView/>
</ListView.View>
</ListView>
I want to set the background of the second row (for example) to red programmatically.
What should I do?
Thanks.
You can use a similar approach:
int index = 1;
ListViewItem row = ListView.ItemContainerGenerator.ContainerFromIndex(index) as ListViewItem;
row.BackGround = Brushes.Red;
You can use AlternationCount to store the index of the row in AlternationIndex, and then use a trigger to set the background of the second row (at index 1) to red:
<ListView AlternationCount="{x:Static sys:Int32.MaxValue}">
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Style.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter Property="Background" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
...
</ListView>
AlternationCount defines the number of rows to count before restarting to zero. For example, if set to 2, the indexes for the rows will be 0 1 0 1 0 1 ..., allowing you to paint to red only the odd or even rows. Setting it to MaxValue will never restart the count, effectively setting AlternationIndex to the actual index.
Please clarify one thing here nick. Can you tell me whether you want to just make the color of the second row to red. If that is the case you can iterate through the list view and then keep a count variable on the top and then when the count == 1 then you can change the list view.background color to red. if you have tried this then can you tell me what happened. Does it ended with error or something or nothing happened.
Related
I have such DataGrid
In order to get order number automatically I added in DataGrid method LoadingRow such way
.xalm
...
<DataGrid ItemsSource="{Binding Path=GridItems}"
HorizontalGridLinesBrush="Gray"
RowHeaderWidth="20"
LoadingRow="Dg_main_configuration_LoadingRow"
CanUserReorderColumns="False"
CanUserDeleteRows="False"
CanUserResizeRows="False"
CanUserSortColumns="False"
VerticalGridLinesBrush="LightGray"
x:Name="Dg_main_configuration"
CanUserResizeColumns="False"
PreviewMouseLeftButtonUp="Dg_main_configuration_PreviewMouseLeftButtonUp"
AlternatingRowBackground="LightYellow"
CanUserAddRows="False"
MinHeight="350"
MaxHeight="350"
Grid.Column="0"
AutoGenerateColumns="False">
...
and in code
private void Dg_main_configuration_LoadingRow(object sender, DataGridRowEventArgs e)
{
e.Row.Header = (e.Row.GetIndex() + 1).ToString();
}
All is fine, but anyway I would like to adjust this row column
Problems is :
You can see in screenshot next to Path to clip folder(on the left) there is a cell with a rectangle at the right bottom, acctually it is kind of button(because I can click on it, but nothing changed), how to disable it, or set symbol like #?
Numbers 1, 2, 3, 4 horizontally not in the center, how to fix it?
And last is - you can see that there are a horizontal lines DarkGray that separates rows, but I don't know why numbers doesn't include this separate lines? I mean line starts after number column. How to include separate line in order numbers also?
You could display the row number in a column, for example using the approach mentioned here.
You could then use an ElementStyle to center the TextBlock:
<DataGridTextColumn Binding="{Binding RelativeSource={RelativeSource AncestorType=DataGridRow},
Converter={local:RowToIndexConverter}}">
<DataGridTextColumn.ElementStyle>
<Style TargetType="TextBlock">
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
</DataGridTextColumn.ElementStyle>
</DataGridTextColumn>
For point 2 (and may also get you understand more about point 3). A DataGrid can have a RowHeaderTemplate (or an even more general RowHeaderStyle) which would be applied to each row header value (that you set in code). Here is a related question.
For point 1 (and also for point 2 for the default row header template, and point 3) I suggest you to look at Microsoft's default DataGrid styles and templates. You might need to set the entire DataGrid template to change the top-left part (or try having a resource with key {ComponentResourceKey ResourceId=DataGridSelectAllButtonStyle, TypeInTargetAssembly={x:Type DataGrid}}) - that is the DataGridSelectAllButtonStyle, which supposedly is a button that would select all rows if the rows can be selected in the data grid.
For point 3, to set up the horizontal grid lines to a different color (e.g. matching row headers' separator) use HorizontalGridLinesBrush property.
I have a DataGrid that's bound to Datatable, and I want to uniquely identify rows in the DataTable using the ID, but I don't want it to be shown in the DataGrid
What I reached so far by searching and excluding:
Data columns are not predefined, so, I have to use AutoGenerateColumns=True, hence, I can't define the columns manually and set the Visibility property to False.
I can't use List or ObservableCollection to define private ID member, because the data are dynamic.
I am following MVVM so, I can't use AutoGeneratingColumns event handler directly and can't expose the View to the ViewModel.
The closest I get to an answer is using DataTrigger to set Visibility to False using CellStyle, but it just hid the cells, not the entire column, and I also tried it for DataGridColumnHeader and it didn't work:
code:
<Style x:Key="ColumnStyle" TargetType="DataGridColumnHeader">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Value}" Value="id">
<Setter Property="Visibility" Value="Hidden"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
How to do it while maintaining the previous conditions?
Thanks in advance
EDIT:
I fixed the code for DataGridColumnHeader using Path=Column.Header which doesn't make sense to me but it's irrelevant; Still, there and empty column standing there, with no idea how to remove it.
It sounds like you want to track the selected Item. If you want to track the "selected Element", you have to use a CollectionView.
WPF controls do not direcly bind to collections. They bind to a CollectionView. And if you do not give them one, they will create one themself from whatever collection you hand them. If you want sorting, filtering, ordering and selection tracking, CollectionView is the droid you are looking for:
https://msdn.microsoft.com/en-us/library/system.windows.data.collectionview.aspx
Just take control of it's creation and expose it (rather then the raw collection).
I found a solution by applying this style:
<Style x:Key="ColumnStyle" TargetType="DataGridColumnHeader">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Value}" Value="id">
<Setter Property="Visibility" Value="Hidden"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
to DataGridCell and to DataGridColumnHeader and allocating the column in the end of the table this removed the empty column from the middle of the table.
I have a scenario which requires me to bind a list of objects to a grid. I would like the behaviour as such that :-
• When an item is added to the list it moves to the next available space in the grid. (like a wrap panel)
Shown below is my current XAML.
<ItemsControl ItemsSource="{Binding Path=Contents}" Grid.Row="1">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<cc:DynamicGrid ShowGridLines="True" RowCount="{Binding Path= SelectedGridStyle.RowCount}" ColCount="{Binding Path=SelectedGridStyle.ColCount}"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
Currently this puts all of the items on top of each other because I have not specified a row index or column index. I plan to add the following to rectify this
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Grid.Column" Value="{Binding Path=ColumnIndex}"/>
<Setter Property="Grid.Row" Value="{Binding Path=RowIndex}"/>
<Setter Property="Grid.ColumnSpan" Value="{Binding Path=ColumnSpan}"/>
<Setter Property="Grid.RowSpan" Value="{Binding Path=RowSpan}"/>
</Style>
</ItemsControl.ItemContainerStyle>
I have the following code which will allow me to calculate the rowIndex and columnIndex from the index in the list.
int m_ColumnCount = 3;
int rowIndex = index / m_ColumnCount;
int columnIndex = index - (rowIndex * m_ColumnCount);
I am attempting to create a binding converter using the above to set these values. However this calculation depends on values held in the view model for the number of columns and rows. Is there a way to get these values?Can the above be achieved or is there a better solution?
Check out this - http://www.switchonthecode.com/tutorials/wpf-tutorial-using-multibindings
You will see about half way down the use of the multibinding, it's pretty simple. Then they show you how to create a converter for it. Sounds like you are familiar with converters so I think that article will get you moving.
If a binding needs more than one value you could use a MultiBinding. To bind to the main viewmodel you can use a RelativeSource targeting the ItemsControl.
Tried to do some searching on this, but couldn't find exactly what I needed. I'd like to have a combobox with hardcoded items, but contain a default string. For example:
--Select Item--
Item1
Item2
Item3
I do not want the --Select Item-- to appear within the list, only on the combobox itself.
Also I do not want this value to be editable.
Thanks.
You could override the default template and to include a TextBlock there which only is visible if the SelectedItem is null (use a style with datatrigger for that). To get a default tenmplate you can modify check MSDN (Default WPF Themes link).
To do this you'll have to extened the combo box class and add this additional fundtionality. I'd start by writing a method to accept a default value, then write a new method for retrieving the list of items that excludes the default item.
You may also want to handle returning NULL when the default value is selected, as well maybe looking into adjusting the selected index of selected items to account for having an extra item in the list, for example
I think the easiest way to do this is with a simple style:
<ComboBox>
<ComboBox.Style>
<Style TargetType="ComboBox">
<Setter Property="IsEditable" Value="True" />
<Setter Property="IsReadOnly" Value="True" />
<Style.Triggers>
<Trigger Property="SelectedIndex" Value="-1">
<Setter Property="Text" Value="-- Select Item --" />
</Trigger>
</Style.Triggers>
</Style>
</ComboBox.Style>
</ComboBox>
Setting the IsEditable="True" enables the Text property on the ComboBox. In order to ensure that the Text property can not be edited, IsReadOnly="True" is also required.
I have a ListBox bound to a list of Items (for arguement, lets say its got a string and two dates Entered and Done).
I would like to make the background color of items in the ListBox have a gray color if the Done DateTime is != DateTime.MinValue.
Edit:
Should I make a converter? and convert DateTime to a Brush based on the value of the DateTime?
Is something like this my best option? or is there a simple Xaml snippet I could use?
[ValueConversion(typeof(DateTime), typeof(Brush))]
class MyConverter : IValueConverter
{
...
}
A ValueConverter would work. Another option would be to use a DataTrigger in the style of ListBoxItem. Maybe something like this:
<Style x:Name="MinDateTimeListBoxStyle" TargetType="ListBoxItem">
<Style.Triggers>
<Setter Property="Background" Value="Gray" />
<DataTrigger Binding="{Binding Path=Done}"
Value="{x:Static sys:DateTime.MinValue}">
<Setter Property="Background" Value="White" />
</DataTrigger>
</Style.Triggers>
</Style>
This will set the background to Gray when the value of Done isn't DateTime.MinValue. I don't think there is a way to do a not equals comparison in a trigger, so it sets the background to Gray by default, and only changing it back to white if Done hasn't changed yet. It would probably be better to use the correct color for the background instead of white (maybe get the value of the parent's background?), but this should give you something to start with.
Update: To apply this style to the items of only certain ListBoxes, give the style a name and set the ItemContainerStyle as appropriate:
<ListBox x:Name="StyledListBox"
ItemContainerStyle="{StaticResource MinDateTimeListBoxStyle}" />
<ListBox x:Name="NormalListBox" />