it-swarm.com.de

Xamarin.Forms ListView: Legt die Hervorhebungsfarbe eines berührten Elements fest

Wie kann ich mit Xamarin.Forms die Hervorhebungs-/Hintergrundfarbe eines ausgewählten/angezogenen ListView-Elements definieren?

(Meine Liste hat einen schwarzen Hintergrund und eine weiße Textfarbe, daher ist die Standard-Hervorhebungsfarbe unter iOS zu hell. Im Gegensatz dazu gibt es unter Android keine Hervorhebung - bis zu einer subtilen horizontalen grauen Linie.)

Beispiel: (links: iOS, rechts: Android; beim Drücken von "Barn2")

39
Falko

iOS

Lösung:

In einem benutzerdefinierten ViewCellRenderer können Sie das SelectedBackgroundView festlegen. Erstellen Sie einfach eine neue UIView mit einer Hintergrundfarbe Ihrer Wahl und Sie sind festgelegt.

public override UITableViewCell GetCell(Cell item, UITableView tv)
{
    var cell = base.GetCell(item, tv);

    cell.SelectedBackgroundView = new UIView {
        BackgroundColor = UIColor.DarkGray,
    };

    return cell;
}

Ergebnis:

Hinweis:

Bei Xamarin.Forms scheint es wichtig zu sein, ein newUIView zu erstellen, anstatt nur die Hintergrundfarbe des aktuellen festzulegen.


Android

Lösung:

Die Lösung, die ich unter Android gefunden habe, ist etwas komplizierter:

  1. Erstellen Sie einen neuen Zeichencode ViewCellBackground.xml im Ordner Resources> drawable:

    <?xml version="1.0" encoding="UTF-8" ?>
    <selector xmlns:Android="http://schemas.Android.com/apk/res/Android">
        <item Android:state_pressed="true" >
            <shape Android:shape="rectangle">
                <solid Android:color="#333333" />
            </shape>
        </item>
        <item>
            <shape Android:shape="rectangle">
                <solid Android:color="#000000" />
            </shape>
        </item>
    </selector>
    

    Sie definiert Volumenkörper mit unterschiedlichen Farben für den Standardzustand und den "gedrückten" Zustand eines Oberflächenelements.

  2. Verwenden Sie eine geerbte Klasse für das View Ihres ViewCell, z. B.

    public class TouchableStackLayout: StackLayout
    {
    }
    
  3. Implementieren Sie einen benutzerdefinierten Renderer für diese Klasse, indem Sie die Hintergrundressource festlegen:

    public class ElementRenderer: VisualElementRenderer<Xamarin.Forms.View>
    {
        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.View> e)
        {
            SetBackgroundResource(Resource.Drawable.ViewCellBackground);
    
            base.OnElementChanged(e);
        }
    }
    

Ergebnis:

21
Falko

In Android bearbeiten Sie einfach Ihre Style.xml-Datei unter Resources\Value und fügen Sie Folgendes hinzu:

<resources>
  <style name="MyTheme" parent="Android:style/Theme.Material.Light.DarkActionBar">
   <item name="Android:colorPressedHighlight">@color/ListViewSelected</item>
   <item name="Android:colorLongPressedHighlight">@color/ListViewHighlighted</item>
   <item name="Android:colorFocusedHighlight">@color/ListViewSelected</item>
   <item name="Android:colorActivatedHighlight">@color/ListViewSelected</item>
   <item name="Android:activatedBackgroundIndicator">@color/ListViewSelected</item>
  </style>
<color name="ListViewSelected">#96BCE3</color>
<color name="ListViewHighlighted">#E39696</color>
</resources>
61
mfranc28

Es sieht so aus, als ob es tatsächlich eine plattformübergreifende Methode gibt, die sowohl für iOS als auch für Android funktioniert (nicht sicher über Windows). Es verwendet nur die Bindung und erfordert keine benutzerdefinierten Renderer (was selten erscheint). Dies ist ein Mash-up von viel googeln, also danke an alle, von denen ich vielleicht geliehen habe ... 

Ich gehe davon aus, dass ViewCells verwendet wird, dies sollte jedoch auch für Text- oder Bildzellen funktionieren. Ich füge den entsprechenden Code hier nur über den typischen Text, das Bild usw. hinzu.

Tun Sie auf Ihrer Seite so etwas:

MyModel model1 = new MyModel();
MyModel model2 = new MyModel();

ListView list = new ListView
{
    ItemsSource = new List<MyModel> { model1, model2 };
    ItemTemplate = new DataTemplate( typeof(MyCell) )
};

Ihr benutzerdefiniertes Modell könnte ungefähr so ​​aussehen:

public class MyModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private Color _backgroundColor;

    public Color BackgroundColor 
    { 
        get { return _backgroundColor; } 
        set 
        { 
            _backgroundColor = value; 

            if ( PropertyChanged != null )
            {
                PropertyChanged( this, new PropertyChangedEventArgs( "BackgroundColor" ) );
            }
        }
    }

    public void SetColors( bool isSelected )
    {
        if ( isSelected )
        {
            BackgroundColor = Color.FromRgb( 0.20, 0.20, 1.0 );
        }
        else
        {
            BackgroundColor = Color.FromRgb( 0.95, 0.95, 0.95 ); 
        }
    }
}

Dann benötigen Sie für Ihre ItemTemplate eine benutzerdefinierte Zellklasse, etwa wie folgt:

public class MyCell : ViewCell
{
    public MyCell() : base()
    {
        RelativeLayout layout = new RelativeLayout();
        layout.SetBinding( Layout.BackgroundColorProperty, new Binding( "BackgroundColor" ) );

        View = layout;
    }
}

Führen Sie dann in Ihrem ItemSelected-Ereignishandler die folgenden Schritte aus. Beachten Sie, dass 'selected' eine Instanz von MyModel ist, mit der das aktuell ausgewählte Element verfolgt wird. Ich zeige hier nur Hintergrundfarbe, aber ich verwende diese Technik auch, um die Text- und Detail-Textfarben umzukehren.

private void ItemSelected( object sender, ItemTappedEventArgs args )
{
    // Deselect previous
    if ( selected != null )
    {
        selected.SetColors( false );
    }

    // Select new
    selected = (list.SelectedItem as MyModel);
    selected.SetColors( true );
}

Ich habe Screenshots sowohl von iOS als auch von Android, wenn mich jemand auf 10 Punkte stoßen möchte, damit ich sie tatsächlich posten kann :)

58
Barry Sohl

Ich habe einen ähnlichen Prozess, völlig plattformübergreifend, jedoch verfolge ich den Auswahlstatus selbst und habe dies in XAML gemacht.

 <ListView x:Name="ListView" ItemsSource="{Binding ListSource}" RowHeight="50">
        <ListView.ItemTemplate>
          <DataTemplate>
            <ViewCell>
              <ViewCell.View>
                <ContentView Padding="10" BackgroundColor="{Binding BackgroundColor}">
                  <Label Text="{Binding Name}" HorizontalOptions="Center" TextColor="White" />
                </ContentView>
              </ViewCell.View>
            </ViewCell>
          </DataTemplate>
        </ListView.ItemTemplate>
      </ListView>

Dann im ItemTapped-Ereignis

 ListView.ItemTapped += async (s, e) =>
            {
                var list = ListSource;

                var listItem = list.First(c => c.Id == ((ListItem)e.Item).Id);

                listItem.Selected = !listItem.Selected;

                SelectListSource = list;

                ListView.SelectedItem = null;

            };

Wie Sie sehen, setze ich einfach ListView.SelectedItem auf null, um alle plattformspezifischen Auswahlstile zu entfernen, die ins Spiel kommen.

In meinem Modell habe ich 

        private Boolean _selected;

        public Boolean Selected
        {
            get
            {
                return _selected;
            }
            set
            {
                _selected = value;
                if (PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs("BackgroundColor"));
            }
        }                 

        public Color BackgroundColor
        {
            get
            {
                if (Selected)
                    return Color.Black;
                else
                    return Color.Blue
            }
        }
9
Adam Pedley

Ich hatte das gleiche Problem und ich habe es auch gelöst, indem ich einen benutzerdefinierten Renderer für iOS erstellt habe, wie Falko vorschlägt. Allerdings habe ich die Modifikation der Stile für Android vermieden. Ich habe einen Weg gefunden, einen benutzerdefinierten Renderer für Android zu verwenden.

Es ist ziemlich witzig, dass das ausgewählte Flag für die Android-Ansichtszelle immer falsch ist. Deshalb musste ich ein neues Privateigentum erstellen, um es zu verfolgen. Abgesehen davon denke ich, dass dies einem angemesseneren Muster folgt, wenn Sie benutzerdefinierte Renderer für beide Plattformen verwenden möchten. In meinem Fall habe ich es für TextCell getan, aber ich glaube, dass es für andere CellViews genauso gilt.

Xamarin-Formulare

public class CustomTextCell : TextCell
    {
        /// <summary>
        /// The SelectedBackgroundColor property.
        /// </summary>
        public static readonly BindableProperty SelectedBackgroundColorProperty =
            BindableProperty.Create("SelectedBackgroundColor", typeof(Color), typeof(CustomTextCell), Color.Default);

        /// <summary>
        /// Gets or sets the SelectedBackgroundColor.
        /// </summary>
        public Color SelectedBackgroundColor
        {
            get { return (Color)GetValue(SelectedBackgroundColorProperty); }
            set { SetValue(SelectedBackgroundColorProperty, value); }
        }
    }

iOS

public class CustomTextCellRenderer : TextCellRenderer
    {
        public override UITableViewCell GetCell(Cell item, UITableViewCell reusableCell, UITableView tv)
        {
            var cell = base.GetCell(item, reusableCell, tv);
            var view = item as CustomTextCell;
            cell.SelectedBackgroundView = new UIView
            {
                BackgroundColor = view.SelectedBackgroundColor.ToUIColor(),
            };

            return cell;
        }
    }

Android

public class CustomTextCellRenderer : TextCellRenderer
{
    private Android.Views.View cellCore;
    private Drawable unselectedBackground;
    private bool selected;

    protected override Android.Views.View GetCellCore(Cell item, Android.Views.View convertView, ViewGroup parent, Context context)
    {
        cellCore = base.GetCellCore(item, convertView, parent, context);

        // Save original background to rollback to it when not selected,
        // We assume that no cells will be selected on creation.
        selected = false;
        unselectedBackground = cellCore.Background;

        return cellCore;
    }

    protected override void OnCellPropertyChanged(object sender, PropertyChangedEventArgs args)
    {
        base.OnCellPropertyChanged(sender, args);

        if (args.PropertyName == "IsSelected")
        {
            // I had to create a property to track the selection because cellCore.Selected is always false.
            // Toggle selection
            selected = !selected;

            if (selected)
            {
                var customTextCell = sender as CustomTextCell;
                cellCore.SetBackgroundColor(customTextCell.SelectedBackgroundColor.ToAndroid());
            }
            else
            {
                cellCore.SetBackground(unselectedBackground);
            }
        }
    }
}
9
alexcons

Hier ist der rein plattformübergreifende und saubere Weg:

1) Definieren Sie eine Auslöseraktion

namespace CustomTriggers {
   public class DeselectListViewItemAction:TriggerAction<ListView> {
       protected override void Invoke(ListView sender) {
                sender.SelectedItem = null;
       }
   }
}

2) Wenden Sie die obige Klasseninstanz als EventTrigger-Aktion in XAML wie folgt an

 <ListView x:Name="YourListView" ItemsSource="{Binding ViewModelItems}">
    <ListView.Triggers>
        <EventTrigger Event="ItemSelected">
            <customTriggers:DeselectListViewItemAction></customTriggers:DeselectListViewItemAction>
        </EventTrigger>
    </ListView.Triggers>
</ListView>

Vergessen Sie nicht, xmlns:customTriggers="clr-namespace:CustomTriggers;Assembly=ProjectAssembly" hinzuzufügen.

Hinweis: Da sich keines Ihrer Objekte im ausgewählten Modus befindet, wird das Auswahlstiling auf keiner der Plattformen angewendet.

5
Zafar Ameem

Um die Farbe des hervorgehobenen Elements einzustellen, müssen Sie in iOS die Farbe von cell.SelectionStyle einstellen. 

In diesem Beispiel wird die Farbe des berührten Elements auf transparent gesetzt. 

Wenn Sie möchten, können Sie es mit anderen Farben in UITableViewCellSelectionStyle ändern. Dies soll in das Plattformprojekt von iOS geschrieben werden, indem ein neuer Custom ListView-Renderer in Ihrem Forms-Projekt erstellt wird. 

public class CustomListViewRenderer : ListViewRenderer
    {
        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);

            if (Control == null)
            {
                return;
            }

            if (e.PropertyName == "ItemsSource")
            {
                foreach (var cell in Control.VisibleCells)
                {
                    cell.SelectionStyle = UITableViewCellSelectionStyle.None;
                }
            }
        }
    }

Für Android können Sie diesen Stil in Ihre Werte/styles.xml einfügen

<style name="ListViewStyle.Light" parent="Android:style/Widget.ListView">
    <item name="Android:listSelector">@Android:color/transparent</item>
    <item name="Android:cacheColorHint">@Android:color/transparent</item>
  </style>

Fand diese schöne Option mit Effekten hier .

iOS:

[Assembly: ResolutionGroupName("MyEffects")]
[Assembly: ExportEffect(typeof(ListViewHighlightEffect), nameof(ListViewHighlightEffect))]
namespace Effects.iOS.Effects
{
    public class ListViewHighlightEffect : PlatformEffect
    {
        protected override void OnAttached()
        {
            var listView = (UIKit.UITableView)Control;

            listView.AllowsSelection = false;
        }

        protected override void OnDetached()
        {
        }
    }
}

Android:

[Assembly: ResolutionGroupName("MyEffects")]
[Assembly: ExportEffect(typeof(ListViewHighlightEffect), nameof(ListViewHighlightEffect))]
namespace Effects.Droid.Effects
{
    public class ListViewHighlightEffect : PlatformEffect
    {
        protected override void OnAttached()
        {
            var listView = (Android.Widget.ListView)Control;

            listView.ChoiceMode = ChoiceMode.None;
        }

        protected override void OnDetached()
        {
        }
    }
}

Formen:

ListView_Demo.Effects.Add(Effect.Resolve($"MyEffects.ListViewHighlightEffect"));
2
Paul Charlton

Nur für Android

Fügen Sie in Ihrem benutzerdefinierten Thema hinzu

<item name="Android:colorActivatedHighlight">@Android:color/transparent</item>
2
JeePakaJP

Um die Farbe der ausgewählten ViewCell zu ändern, gibt es einen einfachen Prozess, ohne den benutzerdefinierten Renderer zu verwenden. Machen Sie das Tapped-Ereignis von Ihrer ViewCell wie unten beschrieben

<ListView.ItemTemplate>
    <DataTemplate>
        <ViewCell Tapped="ViewCell_Tapped">            
        <Label Text="{Binding StudentName}" TextColor="Black" />
        </ViewCell>
    </DataTemplate>
</ListView.ItemTemplate>

Implementieren Sie das Ereignis in Ihrer ContentPage- oder CS-Datei

private void ViewCell_Tapped(object sender, System.EventArgs e)
{
    if(lastCell!=null)
    lastCell.View.BackgroundColor = Color.Transparent;
    var viewCell = (ViewCell)sender;
    if (viewCell.View != null)
    {
        viewCell.View.BackgroundColor = Color.Red;
        lastCell = viewCell;
    }
} 

Deklarieren Sie lastCell oben in Ihrer ContentPage wie folgt ViewCell lastCell;

1
CGPA6.4

Diese Lösung funktioniert gut, wenn Sie jedoch die Caching-Strategie der ListView vom Standardwert abändern, funktioniert sie nicht mehr. Es funktioniert, wenn Sie Ihre ListView wie folgt neu einrichten: listView = new ListView() { ... }; Wenn Sie dies tun, funktioniert es jedoch nicht (der Hintergrund bleibt für das ausgewählte Element grau): listView = new ListView(cachingStrategy:ListViewCachingStrategy.RecycleElement) { ... };

Im Folgenden finden Sie eine Lösung, die auch mit einer nicht standardmäßigen Caching-Strategie funktioniert. Ich ziehe dies anderen Lösungen vor, z. B. wenn der Code in der OnItemSelected-Methode mit einer Bindung aus dem ViewModel für die Hintergrundfarbe gekoppelt ist.

Dank an @Lang_tu_bi_dien, der die Idee hier gepostet hat: Listview Hintergrundfarbe des ausgewählten Elements

Der endgültige Code sieht dann so aus:

Xamarin.Forms-Code:

namespace MyProject
{
    public class ListView2 : ListView
    {
        public ListView2(ListViewCachingStrategy cachingStrategy) : base(cachingStrategy)
        {
        }
    }
}

XAML auf Ihrer Seite:

    <ListView2 x:Name="myListView" ListViewCachingStrategy="RecycleElement" ItemsSource="{Binding ListSource}" RowHeight="50">
        <ListView.ItemTemplate>
          <DataTemplate>
            <ViewCell>
              <ViewCell.View>
                  <Label Text="{Binding Name}" HorizontalOptions="Center" TextColor="White" />
                </ContentView>
              </ViewCell.View>
            </ViewCell>
          </DataTemplate>
        </ListView.ItemTemplate>
    </ListView2>

iOS-spezifischer Renderer:

[Assembly: ExportRenderer(typeof(ListView2), typeof(ListView2Renderer))]
namespace MyProject.iOS
{
    public partial class ListView2Renderer : ListViewRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<ListView> e)
        {
            base.OnElementChanged(e);
            if (Control != null && e != null)
            {
                //oldDelegate = (UITableViewSource)Control.Delegate;
                Control.Delegate = new ListView2Delegate(e.NewElement);
            }
        }
    }


    class ListView2Delegate : UITableViewDelegate
    {
        private ListView _listView;

        internal ListView2Delegate(ListView listView)
        {
            _listView = listView;
        }

        public override void WillDisplay(UITableView tableView, UITableViewCell cell, Foundation.NSIndexPath indexPath)
        {
            cell.SelectedBackgroundView = new UIView()
            {
                BackgroundColor = Color.Red.ToUIColor()
            };
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                _listView = null;
            }
            base.Dispose(disposing);
        }
    }
}

Hinweis: Sie können auf einige Probleme stoßen, weil Sie den Standarddelegaten ersetzen. Weitere Informationen hierzu finden Sie unter Das Festlegen eines Delegat für die Steuerung im benutzerdefinierten Renderer führt zu Funktionsverlust . In meinem Projekt funktioniert alles wie es sollte, wenn ich das mache:

  • Verwenden Sie die normale ListView zusammen mit dem ListItemViewCellRenderer-Code, der in den vorherigen Beiträgen dieses Threads für ListViews angegeben ist, die die standardmäßige Caching-Strategie ListViewCachingStrategy.RetainElement verwenden.

  • Verwenden Sie diese ListView2 zusammen für ListViews, die eine nicht standardmäßige Caching-Strategie verwenden, d. H. ListViewCachingStrategy.RecycleElement oder ListViewCachingStrategy.RecycleElementAndDataTemplate.

Ich reiche auch eine Funktionsanforderung bei Xamarin ein. Wenn Sie der Meinung sind, dass dies zur Standard-ListView hinzugefügt werden sollte, stimmen Sie dies bitte zu: ListView benötigt dringend eine SelectedItemBackgroundColor-Eigenschaft

1
user2935274

Ich habe und verwende eine Lösung, die @ adam-pedley ähnelt. Keine benutzerdefinierten Renderer. In xaml binde ich die ViewCell-Eigenschaft im Hintergrund

                <ListView x:Name="placesListView" Grid.Row="2" Grid.ColumnSpan="3" ItemsSource="{Binding PlacesCollection}" SelectedItem="{Binding PlaceItemSelected}">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <ViewCell>
                            <Grid BackgroundColor="{Binding IsSelected,Converter={StaticResource boolToColor}}">
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="auto"/>
                                    <RowDefinition Height="auto"/>
                                </Grid.RowDefinitions>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="*" />
                                    <ColumnDefinition Width="*" />
                                </Grid.ColumnDefinitions>

                                <Label Grid.Row="1" Grid.ColumnSpan="2" Text="{Binding DisplayName}" Style="{StaticResource blubeLabelBlackItalic}" FontSize="Default" HorizontalOptions="Start" />
                                <Label Grid.Row="2" Grid.ColumnSpan="2" Text="{Binding DisplayDetail}"  Style="{StaticResource blubeLabelGrayItalic}" FontSize="Small" HorizontalOptions="Start"/>
                                <!--
                                <Label Grid.RowSpan="2" Grid.ColumnSpan="2" Text="{Binding KmDistance}"  Style="{StaticResource blubeLabelGrayItalic}" FontSize="Default" HorizontalOptions="End" VerticalOptions="Center"/>
                                -->
                            </Grid>
                        </ViewCell>
                    </DataTemplate>
                </ListView.ItemTemplate>                    
            </ListView>

Im Code (MVVM) speichere ich die letzte von einem BoolToColor Converter ausgewählte Hintergrundfarbe

    public class BoolToColorConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return (bool)value ? Color.Yellow : Color.White;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return (Color)value == Color.Yellow ? true : false;
        }
    }

    PlaceItem LastItemSelected;

    PlaceItem placeItemSelected;
    public PlaceItem PlaceItemSelected
    {
        get
        {
            return placeItemSelected;
        }

        set
        {
            if (LastItemSelected != null)
                LastItemSelected.IsSelected = false;

            placeItemSelected = value;
            if (placeItemSelected != null)
            {
                placeItemSelected.IsSelected = true;
                LastItemSelected = placeItemSelected;
            }
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(PlaceItemSelected)));
        }
    }

Mein Beispiel wird durch eine Listenansicht von Orten extrahiert, die sich in Xamarin Forms Maps (gleiche Inhaltsseite) befinden .. Ich hoffe, dass diese Lösung für jemanden nützlich ist

1

Der einfachste Weg, dies auf Android zu erreichen, besteht darin, den folgenden Code zu Ihrem benutzerdefinierten Stil hinzuzufügen: 

@Android: Farbe/transparent

1
Damien Doumer

In den vorherigen Antworten werden entweder benutzerdefinierte Renderer vorgeschlagen oder Sie müssen das ausgewählte Element entweder in Ihren Datenobjekten oder auf andere Weise nachverfolgen. Dies ist nicht wirklich erforderlich, es gibt eine Möglichkeit, sich plattformunabhängig mit der Funktionsweise der ListView zu verbinden. Dies kann dann verwendet werden, um den ausgewählten Artikel auf beliebige Weise zu ändern. Je nach ausgewähltem Zustand können Farben geändert, verschiedene Teile der Zelle angezeigt oder ausgeblendet werden.

Fügen wir unserer IsSelected eine ViewCell -Eigenschaft hinzu. Es ist nicht erforderlich, es dem Datenobjekt hinzuzufügen. Die Listenansicht wählt die Zelle aus, nicht die gebundenen Daten.

public partial class SelectableCell : ViewCell {

  public static readonly BindableProperty IsSelectedProperty = BindableProperty.Create(nameof(IsSelected), typeof(bool), typeof(SelectableCell), false, propertyChanged: OnIsSelectedPropertyChanged);
  public bool IsSelected {
    get => (bool)GetValue(IsSelectedProperty);
    set => SetValue(IsSelectedProperty, value);
  }

  // You can omit this if you only want to use IsSelected via binding in XAML
  private static void OnIsSelectedPropertyChanged(BindableObject bindable, object oldValue, object newValue) {
    var cell = ((SelectableCell)bindable);
    // change color, visibility, whatever depending on (bool)newValue
  }

  // ...
}

Um die fehlende Verknüpfung zwischen den Zellen und der Auswahl in der Listenansicht zu erstellen, benötigen wir einen Konverter (die ursprüngliche Idee kam aus dem Xamarin Forum ):

public class IsSelectedConverter : IValueConverter {
  public object Convert(object value, Type targetType, object parameter, CultureInfo culture) =>
    value != null && value == ((ViewCell)parameter).View.BindingContext;

  public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) =>
    throw new NotImplementedException();
}

Wir verbinden die beiden mit diesem Konverter:

<ListView x:Name="ListViewName">
  <ListView.ItemTemplate>
    <DataTemplate>
      <local:SelectableCell x:Name="ListViewCell"
        IsSelected="{Binding SelectedItem, Source={x:Reference ListViewName}, Converter={StaticResource IsSelectedConverter}, ConverterParameter={x:Reference ListViewCell}}" />
    </DataTemplate>
  </ListView.ItemTemplate>
</ListView>

Diese relativ komplexe Bindung dient dazu zu prüfen, welcher Artikel aktuell ausgewählt ist. Es vergleicht die SelectedItem-Eigenschaft der Listenansicht mit der BindingContext der Ansicht in der Zelle. Dieser Bindungskontext ist das Datenobjekt, an das wir tatsächlich binden. Mit anderen Worten, es wird geprüft, ob das Datenobjekt, auf das mit SelectedItem verwiesen wird, tatsächlich das Datenobjekt in der Zelle ist. Wenn sie gleich sind, haben wir die ausgewählte Zelle. Wir binden dies in die IsSelected-Eigenschaft, die dann in XAML oder hinterem Code verwendet werden kann, um festzustellen, ob sich die Ansichtszelle im ausgewählten Status befindet.

Es gibt nur eine Einschränkung: Wenn Sie ein standardmäßig ausgewähltes Element festlegen möchten, wenn Ihre Seite angezeigt wird, müssen Sie etwas klug sein. Leider hat Xamarin Forms keine Seite Angezeigtes Ereignis, wir haben nur Appearing und dies ist zu früh für die Standardeinstellung: Die Bindung wird dann nicht ausgeführt. Verwenden Sie also eine kurze Verzögerung:

protected override async void OnAppearing() {
  base.OnAppearing();

  Device.BeginInvokeOnMainThread(async () => {
    await Task.Delay(100);
    ListViewName.SelectedItem = ...;
  });
}
0
Gábor