2014-08-31 3 views
12

Я работаю над проектом C# для Windows Phone 8.1, и я не могу поверить, что я уже потратил впустую почти на день, чтобы найти решение для такая тривиальная проблема:Как изменить цвет выбранного элемента ListView [WP8.1]

У меня есть страница, определенная с помощью XAML, на этой странице у меня есть ListView. В какой-то момент я хочу, чтобы один из элементов списка был выбран, поэтому я вызываю myListView.SelectedIndex = что угодно. Теперь я хочу, чтобы этот элемент отличался визуально от других элементов, например, его текст был нарисован другим цветом. Как мне это сделать? Вот соответствующие части кода:

<Page.Resources> 
    <DataTemplate x:Key="myListItemTemplate"> 
     <TextBlock 
      Text="{Binding displayName}" 
      Style="{ThemeResource ListViewItemTextBlockStyle}" 
      /> 
    </DataTemplate> 
</Page.Resources> 

<ListView 
    x:Name="myListView" 
    ItemsSource="{Binding}" 
    ItemTemplate="{StaticResource myListItemTemplate}" 
    > 
</ListView> 

Возможно ли с помощью XAML? Или может быть сделано в коде C#, только когда я устанавливаю значение myListView.SelectedIndex?

Спасибо!

+0

Привет, Андрей, вы можете легко адаптировать код, который у меня есть для LongListSelector, к ListView довольно просто. Думаю, я объясню это довольно хорошо. Взгляните: http://stackoverflow.com/questions/25070203/wp8-highlight-selecteditem-longlistselector/25101536#25101536 –

+0

Я пробовал такой подход, но он работает слишком медленно, когда список элементов большой. Я надеялся, что можно указать стиль выбранного элемента в самом XAML, а не задавать цвет в данных, перебирая всю коллекцию. –

+0

Да, решение лишено какой-либо оптимизации, поэтому люди могут понять это лучше. Если вы хотите избежать цикла, вам необходимо привязать выбранный элемент к вашему ViewModel, и когда это изменит, события повысятся. Если вы хотите получить полное решение XAML, я, возможно, напишу вам образец, когда вернусь домой. –

ответ

26

K, Andrei Я думаю, что предлагаемые решения неплохие, это просто глючит. Вот моя.

XAML: Обратите внимание на SelectedUnfocused


<ListView x:Name="mylistview"> 
     <ListView.ItemContainerStyle> 
      <Style TargetType="ListViewItem">      
       <Setter Property="Template"> 
        <Setter.Value> 
         <ControlTemplate TargetType="ListViewItem">         
          <Grid> 
           <VisualStateManager.VisualStateGroups> 
            <VisualStateGroup x:Name="CommonStates"> 
             <VisualState x:Name="Normal"/> 
            </VisualStateGroup> 
            <VisualStateGroup x:Name="SelectionStates"> 
             <VisualState x:Name="Unselected"> 
              <Storyboard> 
               <ColorAnimation Duration="0" Storyboard.TargetName="myback" Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)" To="Transparent"/> 
              </Storyboard> 
             </VisualState> 
             <VisualState x:Name="SelectedUnfocused">             
              <Storyboard> 
               <ColorAnimation Duration="0" Storyboard.TargetName="myback" Storyboard.TargetProperty="(Border.Background).(SolidColorBrush.Color)" To="Red"/> 
              </Storyboard> 
             </VisualState> 
            </VisualStateGroup> 
           </VisualStateManager.VisualStateGroups> 
           <Border x:Name="myback" Background="Transparent"> 
            <ContentPresenter Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}"/> 
           </Border> 
          </Grid>         
         </ControlTemplate> 
        </Setter.Value> 
       </Setter> 
      </Style> 
     </ListView.ItemContainerStyle> 
     <ListView.ItemTemplate> 
      <DataTemplate> 
       <StackPanel Height="100"> 
       <TextBlock Text="{Binding Artist}" FontSize="22"/> 
       <TextBlock Text="{Binding Song}" FontSize="22"/> 
       </StackPanel> 
      </DataTemplate> 
     </ListView.ItemTemplate> 
    </ListView>   

C# (модель выборки)

public class sample_data 
{ 
    public sample_data(string artist, string song) 
    { 
     this.Artist = artist; 
     this.Song = song; 
    } 

    public string Artist { get; set; } 
    public string Song { get; set; } 
} 

private ObservableCollection<sample_data> CreateData() 
{ 
    //List<sample_data> my_list = new List<sample_data>(); 
    ObservableCollection<sample_data> my_list = new ObservableCollection<sample_data>(); 

    my_list.Add(new sample_data("Faith + 1", "Body of Christ")); 
    my_list.Add(new sample_data("Faith + 1", "Christ Again")); 
    my_list.Add(new sample_data("Faith + 1", "A Night With the Lord")); 
    my_list.Add(new sample_data("Faith + 1", "Touch Me Jesus")); 
    my_list.Add(new sample_data("Faith + 1", "I Found Jesus (With Someone Else)")); 
    my_list.Add(new sample_data("Faith + 1", "Savior Self")); 
    my_list.Add(new sample_data("Faith + 1", "Christ What a Day")); 
    my_list.Add(new sample_data("Faith + 1", "Three Times My Savior")); 
    my_list.Add(new sample_data("Faith + 1", "Jesus Touched Me")); 
    my_list.Add(new sample_data("Faith + 1", "Lord is my Savior")); 
    my_list.Add(new sample_data("Faith + 1", "I Wasn't Born Again Yesterday")); 
    my_list.Add(new sample_data("Faith + 1", "Pleasing Jesus")); 
    my_list.Add(new sample_data("Faith + 1", "Jesus (Looks Kinda Hot)")); 
    my_list.Add(new sample_data("Butters", "What What")); 
    return my_list; 
} 

private void Page_Loaded(object sender, RoutedEventArgs e) 
{ 
    ObservableCollection<sample_data> sd = this.CreateData(); 
    mylistview.ItemsSource = sd; 
} 

Скриншот его запуска:

enter image description here

+0

Это работает, спасибо большое! –

+0

Превосходный ответ. Он отлично работал для меня. Спасибо. –

+0

Прошу прощения, но если я хочу использовать привязку к свойству в моем классе, а также использовать это для определения пользовательских стилей? Я хочу использовать '{Binding Property}' внутри 'ControlTemplate'. – vrwim

0

Вам необходимо создать стиль для вашего ListBoxItem и использовать раскадровки.

Вот пример:

<Page.Resources> 
<Style x:Key="ListViewItemTemplate" TargetType="ListViewItem"> 
    <Setter Property="Template"> 
    <Setter.Value> 
     <ControlTemplate TargetType="ListViewItem"> 
     <Border x:Name="LayoutRoot"> 
      <VisualStateManager.VisualStateGroups> 
      <VisualStateGroup x:Name="SelectionStates"> 
       <VisualState x:Name="Unselected"> 
       <Storyboard> 
        <!-- Define style --> 
        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="container" Storyboard.TargetProperty="Background"> 
        <DiscreteObjectKeyFrame KeyTime="0" Value="Transparent"/> 
        </ObjectAnimationUsingKeyFrames> 
       </Storyboard> 
       </VisualState> 
       <VisualState x:Name="Selected"> 
       <Storyboard> 
        <!-- Define style --> 
        <ObjectAnimationUsingKeyFrames Storyboard.TargetName="container" Storyboard.TargetProperty="Background"> 
        <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneAccentBrush}"/> 
        </ObjectAnimationUsingKeyFrames> 
       </Storyboard> 
       </VisualState> 
      </VisualStateGroup> 
      </VisualStateManager.VisualStateGroups> 
      <Grid Margin="0,5" x:Name="container" Background="Transparent"> 
      <!-- Definition of your list item. --> 
      </Grid> 
     </Border> 
     </ControlTemplate> 
    </Setter.Value> 
    </Setter> 
</Style> 

И определение представления списка:

<ListView ItemContainerStyle="{StaticResource ListViewItemTemplate}" SelectionMode="Single" /> 
+0

Я добавил фрагмент кода, который вы предоставили моему XAML, однако он не изменил внешний вид выбранного элемента. Любые другие предложения? Благодарю. –

+0

SelectionMode уже одинарный, по умолчанию. После того, как я добавил ItemContainerStyle в ListView, что-то изменилось, и ваш код, похоже, начнет действовать, но он сломал привязку данных: список больше не заполняется из источника данных модели. –

+1

Официально сейчас: целый день потрачен впустую, просто пытаясь изменить цвет выбранного предмета ... –

0

Да это, вам нужно задать стиль с курка на выбранное свойство. Его жесткая привязка к коду на моем телефоне, но быстрый Google покажет вам массу примеров или здесь: ListBox Style Selected item on windows phone

+0

В этом примере используется привязка данных, чтобы изменить выбранное состояние элемента, что отлично подходит для нескольких элементов, но очень неэффективно для больших списков: каждый раз, когда мне нужно менять выделение, мне нужно будет перечислить весь список. Я надеялся на решение, которое не требовало бы этого. –

+0

Я не знаю, что вы читали, но ответ на вопрос, который я связал, использовал шаблон, который был применен к списку. Я также сказал, чтобы использовать триггер свойств для применения стиля. ни одна из них не использует петлевую стратегию. – Steve

+0

Думаю, вы ответили на неправильный комментарий, lol. Комментарий chubosaurus использует циклическую стратегию. – Steve

0

Вы можете добавить в свой класс булевскую переменную IsSelected и преобразовать ее в цвет bg. Например:

<DataTemplate> 
     <Grid Background="{Binding IsSelected, Converter={StaticResource IsSelectedToBackgroundColorConverter}}"> 
      <TextBlock Text="{Binding displayName}" 
         Style="{ThemeResource ListViewItemTextBlockStyle}" /> 
     </Grid> 
    </DataTemplate> 

|

class IsSelectedToBackgroundColorConverter: IValueConverter 
{ 

    public object Convert(object value, Type targetType, object parameter, string language) 
    { 

     bool IsSelected = (bool)value; 

     if (IsSelected) 
     { 
      Windows.UI.Xaml.Media.Brush red = new SolidColorBrush(Windows.UI.Colors.Red); 

      return red; 
     } 
     else 
     { 
      Windows.UI.Xaml.Media.Brush transparent = new SolidColorBrush(Windows.UI.Colors.Transparent); 

      return transparent; 
     } 

    } 

} 
+0

Да, это работает, но медленно, когда набор данных большой. Кроме того, он не слишком хорошо подходит для философии MVVM: свойство «selected» принадлежит представлению, а не данным. Решение, предоставляемое Chubosaurus Software, намного лучше в этом отношении. Спасибо, в любом случае! –

0

Вам просто нужно добавить следующее app.xaml

</Application.Resources> <SolidColorBrush x:Key="ListViewItemSelectedBackgroundThemeBrush" Color="#92D050" /> <Application.Resources>

"гекс-Color" будет выбран цвет элемент в ListView при применении сферы

0

Try это, надеюсь, это может вам помочь.

if (e.AddedItems != null) { 
    foreach (var item in e.AddedItems) { 
     ListViewItem litem = (sender as ListView).ContainerFromItem(item) as ListViewItem; 
     if (litem != null) { 
      VisualStateManager.GoToState(litem, "Unfocused", true); 
      VisualStateManager.GoToState(litem, "Normal", true); 
      VisualStateManager.GoToState(litem, "Selected", true); 
     } 
    } 
} 
if (e.RemovedItems != null) { 
    foreach (var item in e.RemovedItems) { 
     ListViewItem litem = (sender as ListView).ContainerFromItem(item) as ListViewItem; 
     if (litem != null) { 
      VisualStateManager.GoToState(litem, "Unselected", true); 
     } 
    } 
} 
Смежные вопросы