Переменные цвета строк в ListView в Windows Phone 8.1
Я создал приложение под управлением Windows Phone 8.1.
Я использую элемент управления ListView.
Я хочу изменить каждый цвет строки фона.
После поиска я нашел эту ссылку предыдущий ответ.
Но это дает ошибки в разметке. Во-первых, нет свойства AlternationCount. Я предполагаю это потому, что это не SilverLight, а RT?
Если кто-нибудь может отправить мне ссылку, поскольку я изо всех сил пытаюсь найти простой пример. даже лучше использовать простой пример кода.
Ответы
Ответ 1
Мое предложение - использовать класс Converter с дополнительными DependencyProperties. Когда вы инициализируете конвертер, вы определяете, к какой коллекции элементов он относится, и список альтернативных кистей для фона. Он может выглядеть следующим образом:
public class AlternateConverter : DependencyObject, IValueConverter
{
public List<SolidColorBrush> AlternateBrushes
{
get { return (List<SolidColorBrush>)GetValue(AlternateBrushesProperty); }
set { SetValue(AlternateBrushesProperty, value); }
}
public static readonly DependencyProperty AlternateBrushesProperty =
DependencyProperty.Register("AlternateBrushes", typeof(List<SolidColorBrush>),
typeof(AlternateConverter), new PropertyMetadata(new List<SolidColorBrush>()));
public object CurrentList
{
get { return GetValue(CurrentListProperty); }
set { SetValue(CurrentListProperty, value); }
}
public static readonly DependencyProperty CurrentListProperty =
DependencyProperty.Register("CurrentList", typeof(object),
typeof(AlternateConverter), new PropertyMetadata(null));
public object Convert(object value, Type targetType, object parameter, string language)
{ return AlternateBrushes[(CurrentList as IList).IndexOf(value) % AlternateBrushes.Count]; }
public object ConvertBack(object value, Type targetType, object parameter, string language)
{ throw new NotImplementedException(); }
}
Как только вы определили и создали список альтернативных кистей:
// somewhere in your DataContext
private List<SolidColorBrush> brushes = new List<SolidColorBrush> { new SolidColorBrush(Colors.Red), new SolidColorBrush(Colors.Blue) };
public List<SolidColorBrush> Brushes { get { return brushes; } }
Вы можете использовать его следующим образом:
<ListView x:Name="myList" ItemsSource={Binding MyItems}>
<ListView.Resources>
<local:AlternateConverter CurrentList="{Binding ElementName=myList, Path=ItemsSource}"
AlternateBrushes="{Binding Brushes}"
x:Key="AlternateConverter"/>
</ListView.Resources>
<ListView.ItemTemplate>
<DataTemplate>
<Border Background="{Binding Converter={StaticResource AlternateConverter}}">
<!-- your itemtemplate -->
</Border>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Это решение должно работать, хотя у него может быть проблема, когда у вас есть IList типов значений. Также здесь не должно быть проблем с отложенным созданием, поскольку он возвращает индекс непосредственно из списка.
Ответ 2
Я знаю, что уже есть несколько хороших ответов на этот вопрос, но я просто хочу добавить еще одну идею, которая, по моему мнению, немного сложнее реализовать, но проще в использовании.
Для этого решения потребуется помощь от ListView
ItemContainerStyleSelector
и a Behavior
из SDK поведения (XAML).
В принципе, это поведение AlternatingColorItemContainerStyleSelector
, которое я создал, позволяет вам указать два цвета SolidColorBrush
. Он инкапсулирует логику создания ItemContainerStyleSelector
двумя разными Style
, а также назначает соответствующий SolidColorBrush
для каждого Style
.
Как только у вас есть поведение на месте, его использование чрезвычайно просто - мне нужно было только перетащить его на ListView
в Expression Blend и указать два цвета и это!
![enter image description here]()
Здесь поведение.
namespace Behaviors
{
public class AlternatingColorItemContainerStyleSelector : StyleSelector
{
private Style _oddStyle = new Style { TargetType = typeof(ListViewItem) }, _evenStyle = new Style { TargetType = typeof(ListViewItem) };
public Style OddStyle { get { return _oddStyle; } }
public Style EvenStyle { get { return _evenStyle; } }
protected override Style SelectStyleCore(object item, DependencyObject container)
{
var listViewItem = (ListViewItem)container;
var listView = GetParent<ListView>(listViewItem);
var index = listView.IndexFromContainer(listViewItem);
if (index % 2 == 0)
{
return this.EvenStyle;
}
else
{
return this.OddStyle;
}
}
public static T GetParent<T>(DependencyObject child) where T : DependencyObject
{
while (!(child is T))
{
child = VisualTreeHelper.GetParent(child);
}
return (T)child;
}
}
public class ListViewAlternatingColorBehavior : DependencyObject, IBehavior
{
public DependencyObject AssociatedObject { get; set; }
public Style SharedItemContainerStyle { get; set; }
#region colors dp
public SolidColorBrush OddBrush
{
get { return (SolidColorBrush)GetValue(OddBrushProperty); }
set { SetValue(OddBrushProperty, value); }
}
public static readonly DependencyProperty OddBrushProperty =
DependencyProperty.Register("OddBrush", typeof(SolidColorBrush), typeof(ListViewAlternatingColorBehavior), new PropertyMetadata(null));
public SolidColorBrush EvenBrush
{
get { return (SolidColorBrush)GetValue(EvenBrushProperty); }
set { SetValue(EvenBrushProperty, value); }
}
public static readonly DependencyProperty EvenBrushProperty =
DependencyProperty.Register("EvenBrush", typeof(SolidColorBrush), typeof(ListViewAlternatingColorBehavior), new PropertyMetadata(null));
#endregion
public void Attach(DependencyObject associatedObject)
{
this.AssociatedObject = associatedObject;
this.ApplyItemContainerStyleSelectors();
}
private void ApplyItemContainerStyleSelectors()
{
var itemContainerStyleSelector = new AlternatingColorItemContainerStyleSelector();
if (this.SharedItemContainerStyle != null)
{
itemContainerStyleSelector.OddStyle.BasedOn = this.SharedItemContainerStyle;
itemContainerStyleSelector.EvenStyle.BasedOn = this.SharedItemContainerStyle;
}
itemContainerStyleSelector.OddStyle.Setters.Add(new Setter { Property = Control.BackgroundProperty, Value = this.OddBrush });
itemContainerStyleSelector.EvenStyle.Setters.Add(new Setter { Property = Control.BackgroundProperty, Value = this.EvenBrush });
var listView = (ListView)this.AssociatedObject;
listView.ItemContainerStyleSelector = itemContainerStyleSelector;
}
public void Detach()
{
}
}
}
Следует отметить, что удаление элементов не будет обновлять все цвета других элементов (просто потому, что SelectStyleCore
других элементов не будет вызываться), добавив элементы. Но в вашем случае этого должно быть достаточно.
Ответ 3
WPF - единственная инфраструктура, поддерживающая "AlternationCount" - ни Windows Phone, ни Silverlight, ни RT.
Вы можете обнаружить, что самым простым решением является просто добавить свойство "Index" или "IsOdd" в вашу модель строки. Вы можете просто привязать это свойство, используя конвертер, чтобы вернуть соответствующую кисть/цвет в зависимости от индекса.
Один более простой подход заключается в привязке к конвертеру, который отслеживает индекс, используя статическую переменную, как показано ниже. Однако, если вы используете виртуализацию элементов (что вы, вероятно, делаете, если у вас есть только несколько элементов), тогда этот подход сталкивается с сбоями: отложенное создание элементов пользовательского интерфейса приводит к тому, что индексы становятся назначенными вне порядка, и вы заканчиваете с последовательными рядами, отображающими один и тот же цвет.
<Border Background="{Binding Converter={StaticResource AlternatingIndexConverter}}">
public class AlternatingIndexConverter : IValueConverter
{
private static int _index;
public Brush Even { get; set; }
public Brush Odd { get; set; }
public object Convert(...)
{
return (_index++ % 2 == 0 ? Even : Odd);
}
}
Ответ 4
Для меня самый гладкий способ сделать это:
private void ListView_ContainerContentChanging(ListViewBase sender, ContainerContentChangingEventArgs args)
{
if (args.ItemIndex%2 != 0)
{
args.ItemContainer.Background = new SolidColorBrush(Colors.Aqua);
}
else
{
args.ItemContainer.Background = new SolidColorBrush(Colors.White);
}
}
Просто подключите вас к ContainerContentChanging-Event вашего ListView. Я не знаю, работает ли это, когда ваш курорт будет в вашем списке, но для нормального случая он работает очень хорошо.
Вы даже можете реализовать свой собственный ListView, чтобы вы могли использовать его столько, сколько хотите. С помощью правильных свойств вы также можете отредактировать его в файле xaml. Например, присваивание # FFFF0000 (ARGB).
public class BackgroundAlternatingListView : ListView
{
private Color _startColor = Colors.White;
private Color _secondColor = new Color { A = 255, R = 198, G = 198, B = 198 };
public Color StartColor
{
get { return _startColor; }
set { _startColor = value; }
}
public Color SecondColor
{
get { return _secondColor; }
set { _secondColor = value; }
}
public BackgroundAlternatingListView()
{
ContainerContentChanging += BackgroundAlternatingListView_ContainerContentChanging;
}
void BackgroundAlternatingListView_ContainerContentChanging(ListViewBase sender, ContainerContentChangingEventArgs args)
{
if (args.ItemIndex % 2 != 0)
{
args.ItemContainer.Background = new SolidColorBrush(_secondColor);
}
else
{
args.ItemContainer.Background = new SolidColorBrush(_startColor);
}
}
}
Ответ 5
Спасибо за ваши ответы - очень ценю. У меня есть другое решение, которое я хотел бы предложить, и я размещаю его здесь, чтобы люди могли комментировать.
lvwPremises.Items.Clear();
bool toggle = false;
foreach (Premise premise in Shared.Premises)
{
ListViewItem item = new ListViewItem();
item.Content = premise.PremiseName;
if (toggle)
{
item.Background = new SolidColorBrush(Windows.UI.Color.FromArgb(255, 223, 240, 216));
}
else
{
item.Background = new SolidColorBrush(Windows.UI.Color.FromArgb(255, 208, 233, 198));
}
lvwPremises.Items.Add(item);
toggle = !toggle;
}
ИЗМЕНИТЬ - Romasz
Вы всегда можете играть в коде, если хотите, но тогда ваше решение не так универсально, его нужно будет запускать всегда, когда вы меняете коллекцию и могут иметь другие проблемы. Я поместил этот комментарий в качестве редактирования вашего ответа, поэтому приведенный выше код может быть упрощен, и он может выглядеть так (выглядит более приятным в ответе):
private void ColorBackgrounds(ListView list, IList<SolidColorBrush> backgrounds)
{
for (int i = 0; i < list.Items.Count; i++)
(list.ContainerFromIndex(i) as ListViewItem).Background = backgrounds[i % backgrounds.Count];
}