2016-09-28 11 views
0

おそらくやや曖昧なタイトルについて謝罪することから始めましょう。私は問題を説明するのに苦労しています!おそらく、私はこの記事が私の問題に最も近いという私の考えに最も近いGoogleの結果を得ることができないのではないでしょうか。(私は思う):とにかく、私は動的に生成されているニュース記事のリストを持っています。ユーザは、自分のお気に入りリストに記事を追加するために「スター」ボタンを押すという選択肢がある。したがって、この「スター」ボタンは、ユーザーがログインしているときにのみ表示する必要があります。これは、ボタンの可視性をViewModel内のIsLoggedInというプロパティに設定することで、これを達成しようとしています。しかし、これは私のListView内部で起こっているので、ViewModelの代わりに記事の中にIsLoggedInというプロパティーを見つけようとしています。ListViewのDataTypeの代わりにViewModelのバインディングを使用する方法?

私の質問は次のとおりです。データバインドされたリストビュー内のViewModelプロパティにどのようにバインドできますか?

<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> 

要求された記事のクラス:

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; } 
} 

さて、私は、しかし、私ががなければならないと確信している、私のVMのシングルトンを取得する特性を有することにより、作業それを得たので、現在、この作業のような単純なものを得るためのよりクリーンな方法。私はリスト、ViewModel、いくつかのダミーデータ、およびVM内のVisibilityプロパティを持つサンプルrar(OneDriveリンク:https://1drv.ms/u/s!Ar4fOTiwmGYnyWbwRY6rM0eFsL9x)を追加しました。あなたが私の汚い方法なしでそれを稼働させることができるならば、答えとしてコミットすることを自由に感じてください。

+0

あなたは[この回答](http://stackoverflow.com/a/32862922/424129)を見ましたか? –

+0

あなたの質問を 'Articles'クラスで更新できますか – AVK

+0

@EdPlunkettその回答の最後のコードを参照していると思いますか?私の場合はatmで働いているその部分を取得しようとしています。 – anthonytimmers

答えて

0

このタイプの問題は、相対的なバインディングを使用して解決するのが最適です。現在のDataContextに直接バインドするのではなく、この場合ListViewのItemsSource内の個々の項目をバインドするのではなく、任意の祖先要素のプロパティにバインドできます。

を見るにはその項目のDataTemplateで、のTextBlockのTextプロパティがアイテムに直接結合する方法

<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> 

ノートのように定義することができ、簡単なのViewModelクラスに

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"}; } } 
} 

を考えます。

しかし、ボタンの可視性は、それ自身のDataContextではなく、相対バインディングを使用しているListView自体のプロパティにバインドされています。

+0

これは非プリミティブ型のリストでは機能しますか? (私の場合は文字列の代わりに記事) – anthonytimmers

+0

"メンバーAncestorTypeは認識されないか、アクセスできない"というのは、WPFではしか動作しますが、UWPでは動作しないと思います。 – anthonytimmers

+0

私は正しい場所にWindows 10を持っていません今、私はそれをテストすることはできませんが、この質問に受け入れられた答えはhttp://stackoverflow.com/questions/32861612 UWPの答えがあるようだ - ListViewコントロールとElementNameを介してバインディングの名前を付けて – Peregrine

関連する問題