首先让我为可能有点模糊的标题道歉,我很难解释我的问题!也许这就是为什么我很难得到任何谷歌搜索结果,这篇文章最接近我的问题(我认为):How to bind to a property of the ViewModel from within a GridView
无论如何,我有一份动态生成的新闻文章列表。用户可以选择按“星号”按钮以将文章添加到他/她的收藏夹列表中。因此,只有在用户登录时才能看到此“星形”按钮。
我正在尝试通过将Button的Visibility设置为ViewModel中名为IsLoggedIn的属性来实现此目的。但是,因为这发生在我的ListView中,它试图在Article内找到属性IsLoggedIn而不是ViewModel。
所以我想我的问题归结为:如何绑定到Databound ListView中的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="" 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单例的属性来实现它,但是我确信必须有一种更简洁的方法来获得像这样的简单工作。我添加了一个示例rar(OneDrive链接:https://1drv.ms/u/s!Ar4fOTiwmGYnyWbwRY6rM0eFsL9x),它在VM中有一个列表,一个ViewModel,一些虚拟数据和一个Visibility属性。如果你可以在没有我的脏方法的情况下使用它,请随意提交作为答案。
答案 0 :(得分:0)
使用相对绑定可以最好地解决此类型问题。而不是直接绑定到当前的DataContext,即这种情况下ListView的ItemsSource中的单个项,您可以绑定到任何祖先元素的属性。
给出一个简单的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"}; } }
}
然后可以将视图定义为
<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>
请注意,在DataTemplate项中,TextBlock的Text属性直接绑定到该项。
然而,按钮的可见性不仅限于它自己的DataContext,而是绑定到ListView本身,使用相对绑定。