2016-09-28 2 views
0

Lassen Sie mich damit beginnen, mich für den vielleicht etwas vagen Titel zu entschuldigen, es fällt mir schwer, mein Problem zu erklären! Vielleicht ist das der Grund, warum ich kaum Google-Ergebnisse bekomme, da dieser Beitrag meinem Problem am nächsten kommt (glaube ich): How to bind to a property of the ViewModel from within a GridViewWie verwendet man eine Bindung des ViewModel anstelle des DataType eines ListView?

Wie auch immer, ich habe eine Liste von Nachrichtenartikeln, die dynamisch generiert werden. Der Benutzer hat die Möglichkeit, einen "Stern" -Knopf zu drücken, um einen Artikel zu seiner Favoritenliste hinzuzufügen. Dieser "Stern" -Knopf sollte also nur sichtbar sein, wenn der Benutzer angemeldet ist.

Ich versuche dies zu erreichen, indem ich die Sichtbarkeit des Knopfes auf eine Eigenschaft namens IsLoggedIn in meinem ViewModel setze. Da dies jedoch in meinem ListView geschieht, versucht es, die Eigenschaft IsLoggedIn innerhalb von Article anstelle von ViewModel zu finden.

Also meine Fragen läuft auf: Wie kann ich an eine ViewModel-Eigenschaft innerhalb einer Databound ListView binden?

<ListView ItemsSource="{x:Bind VM.Articles, Mode=OneWay}" ItemClick="DebuggableListView_ItemClick" IsItemClickEnabled="True" SelectionMode="None" Grid.Row="1" VerticalAlignment="Top"> 
    <ListView.ItemTemplate> 
     <DataTemplate x:DataType="models:Article"> 
      <Grid Margin="0,10,10,10"> 
       <Grid.ColumnDefinitions> 
        <ColumnDefinition Width="1*"/> 
        <ColumnDefinition Width="4*"/> 
       </Grid.ColumnDefinitions> 

       <Image Source="{Binding Image}" Margin="0,0,10,0" Grid.Column="0" VerticalAlignment="Top" ImageFailed="Image_ImageFailed"/> 
       <Button Visibility="{x:Bind VM.IsLoggedIn, Converter={StaticResource BooleanToVisibilityConverter}, Mode=OneWay}" FontFamily="Segoe MDL2 Assets" Content="&#xE734;" FontSize="30" Background="Transparent" Grid.Column="1" HorizontalAlignment="Right" VerticalAlignment="Bottom"/> 
       <StackPanel Grid.Column="1"> 
        <TextBlock TextWrapping="Wrap" FontWeight="Bold" Text="{Binding Title}"/> 
        <TextBlock TextWrapping="Wrap" Text="{Binding Summary}"/> 
       </StackPanel> 
      </Grid> 
     </DataTemplate> 
    </ListView.ItemTemplate> 
</ListView> 

Angeforderte Artikel Klasse:

public sealed class Article 
{ 
    public int Id { get; set; } 
    public int Feed { get; set; } 
    public string Title { get; set; } 
    public string Summary { get; set; } 
    public DateTime PublishDate { get; set; } 
    public string Image { get; set; } 
    public string Url { get; set; } 
    public string[] Related { get; set; } 
    public Category[] Categories { get; set; } 
    public bool IsLiked { get; set; } 
} 

Okay, ich habe so zur Zeit es durch Arbeiten mit einer Eigenschaft, die die Singleton meiner VM bekommt jedoch ein Ich bin sicher, dass es sein muss, sauberer Weg, um etwas so einfaches Arbeiten zu bekommen. Ich habe ein Beispiel rar hinzugefügt (OneDrive-Link: https://1drv.ms/u/s!Ar4fOTiwmGYnyWbwRY6rM0eFsL9x), die eine Liste, ein ViewModel, einige Dummy-Daten und eine Visibility-Eigenschaft in der VM hat. Wenn Sie es ohne meine schmutzige Methode arbeiten können, zögern Sie nicht, als Antwort zu begehen.

+0

Haben Sie [diese Antwort] (http://stackoverflow.com/a/32862922/424129) angeschaut? –

+0

Können Sie Ihre Frage mit 'Artikel' Klasse aktualisieren – AVK

+0

@EdPlunkett Ich vermute, Sie beziehen sich auf den letzten Teil des Codes in dieser Antwort? Der Versuch, diesen Teil in meinem Fall atm arbeiten zu lassen. – anthonytimmers

Antwort

0

Dieses Typproblem kann am besten mit relativer Bindung gelöst werden. Anstatt direkt an den aktuellen DataContext zu binden, d. H. In diesem Fall an das einzelne Element in der ItemsSource der ListView, können Sie eine Bindung an eine Eigenschaft eines beliebigen Vorgängerelements herstellen.

eine einfache Ansichtsmodell Klasse

Bei
public class ViewModel: ViewModelBase 
{ 
    private bool _isLoggedIn; 
    public bool IsLoggedIn 
    { 
     get { return _isLoggedIn; } 
     set 
     { 
      _isLoggedIn = value; 
      RaisePropertyChanged(() => IsLoggedIn); 
     } 
    } 

    public IEnumerable<string> Items 
    { get { return new[] {"One", "Two", "Theee", "Four", "Five"}; } } 
} 

die Ansicht kann dann als

<Window x:Class="ParentBindingTest.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:local="clr-namespace:ParentBindingTest" 
     Title="MainWindow" 
     Width="300" Height="400"> 

    <Window.DataContext> 
     <local:ViewModel /> 
    </Window.DataContext> 

    <Window.Resources> 
     <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" /> 
    </Window.Resources> 

    <Grid> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="Auto" /> 
      <RowDefinition Height="*" /> 
     </Grid.RowDefinitions> 

     <CheckBox Margin="16,8" HorizontalAlignment="Left" Content="Logged In?" IsChecked="{Binding IsLoggedIn, Mode=TwoWay}" /> 

     <ListView Grid.Row="1" Margin="16,8" ItemsSource="{Binding Items}"> 
      <ListView.ItemTemplate> 
       <DataTemplate> 
        <StackPanel Orientation="Horizontal"> 
         <Button Visibility="{Binding Path=DataContext.IsLoggedIn, RelativeSource={RelativeSource AncestorType={x:Type ListView}}, Converter={StaticResource BooleanToVisibilityConverter}}"> 
          <Image Source="Images\remove.png" /> 
         </Button> 

         <TextBlock Text="{Binding}" /> 
        </StackPanel> 
       </DataTemplate> 
      </ListView.ItemTemplate> 
     </ListView> 
    </Grid> 
</Window> 

Hinweis definiert werden, wie in dem Artikel Datatemplate, die Eigenschaft TextBlock- den Text direkt an das Element gebunden.

Die Sichtbarkeit der Schaltfläche ist jedoch nicht an eine Eigenschaft des eigenen DataContext gebunden, sondern an die der ListView selbst, die relative Bindung verwendet.

+0

Funktioniert das auf einer Liste nicht primitiver Typen? (in meinem Fall Artikel statt String) – anthonytimmers

+0

"Das Mitglied AncestorType wird nicht erkannt oder ist nicht erreichbar", ich schätze, das funktioniert nur in WPF aber nicht auf UWP – anthonytimmers

+0

Ich habe keine Windows 10 wo ich recht habe jetzt, so kann ich es nicht testen, aber die akzeptierte Antwort auf diese Frage http://stackoverflow.com/questions/32861612 scheint die Antwort für UWP zu haben - Benennung der ListView-Steuerelement und die Bindung über ElementName – Peregrine

Verwandte Themen