x:将ListView中的项绑定到ViewModel

时间:2017-04-11 10:08:53

标签: c# listview uwp

你知道当你盯着某个东西时,它已经不再有意义......我试图将listview项的background属性绑定到它是否是viewmodel中集合的一部分。以下是我正在使用的简化版本:

<Grid>

    <ListView x:Name="AirportListView"
              SelectionMode="None"
              IsItemClickEnabled="True"
              ItemClick="AirportListView_ItemClick">

        <ListView.ItemTemplate>

            <DataTemplate x:DataType="x:String">

                <Grid Padding="16">

                    <TextBlock Text="{x:Bind}" />

                </Grid>

            </DataTemplate>

        </ListView.ItemTemplate>            

    </ListView>

</Grid>

public sealed partial class MainPage : Page
{
    public ObservableCollection<string> MyAirports { get; set; } = new ObservableCollection<string>();

    public MainPage()
    {
        this.InitializeComponent();

        AirportListView.ItemsSource = new List<string>()
        {
            "EDDB",
            "LGIR",
            "EHAM",
            "LFPO",
            "EGKK"
        };
    }

    private void AirportListView_ItemClick(object sender, ItemClickEventArgs e)
    {
        if (e.ClickedItem is string clickedAirport)
        {
            if (MyAirports.Contains(clickedAirport))
                MyAirports.Remove(clickedAirport);
            else
                MyAirports.Add(clickedAirport);
        }
    }
}

理想情况下,我想要实现的是在datatemplate中绑定网格的背景,以便当项目是MyAirports的一部分时它是不同的颜色。我只是无法弄清楚如何使用x:Bind或Binding来做到这一点。我可以想到一些更长时间的方法来实现同样的目标,但想知道是否有更优雅的数据绑定解决方案。

任何想法都会非常感激!

威尔

2 个答案:

答案 0 :(得分:0)

你需要使到ItemsSource的集合比一个字符串更丰富。它应该包含属性IsMyAirport,然后它也可以绑定到每个ListViewItem以更新其背景。

<Page ...
    xmlns:local="using:UwpQuestions.Views"
    xmlns:common="using:UwpQuestions.Common">
    <Page.Resources>
        <common:MyBgConverter x:Key="myBgConverter"/>
    </Page.Resources>

<Grid>
    <ListView x:Name="AirportList"
          SelectionMode="None"
          IsItemClickEnabled="True"
          HorizontalContentAlignment="Stretch"
          ItemsSource="{x:Bind Airports}"
          ItemClick="AirportListView_ItemClick">
        <ListView.ItemTemplate>
            <DataTemplate x:DataType="local:AirportItem">
                <Grid Padding="16" Width="150" Background="{x:Bind IsMyAirport, Mode=OneWay, Converter={StaticResource myBgConverter}}">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*"/>
                    </Grid.ColumnDefinitions>
                    <TextBlock Text="{x:Bind Name}" />
                </Grid>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</Grid>
</Page>

后面的代码如下:

public sealed partial class AirportListView : Page
{
    public ObservableCollection<string> MyAirports { get; set; } = new ObservableCollection<string>();
    public ObservableCollection<AirportItem> Airports { get; set; }

    public AirportListView()
    {
        this.InitializeComponent();
        Airports = new ObservableCollection<AirportItem>
        {
            new AirportItem {Name = "EDDB"},
            new AirportItem {Name = "LGIR"},
            new AirportItem {Name = "LFPO"},
            new AirportItem {Name = "EGKK"}
        };
    }

    private void AirportListView_ItemClick(object sender, ItemClickEventArgs e)
    {
        if (e.ClickedItem is AirportItem clickedAirport)
        {
            if (MyAirports.Contains(clickedAirport.Name))
            {
                MyAirports.Remove(clickedAirport.Name);
                clickedAirport.IsMyAirport = false;
            }
            else
            {
                MyAirports.Add(clickedAirport.Name);
                clickedAirport.IsMyAirport = true;
            }
        }
    }
}

public class AirportItem : BindableBase
{
    private string _name;
    public string Name
    {
        get { return _name; }
        set { SetProperty<string>(ref _name, value); }
    }

    private bool _isMyAirport = false;
    public bool IsMyAirport
    {
        get { return _isMyAirport; }
        set { SetProperty<bool>(ref _isMyAirport, value); }
    }
}

AirportItem使用BindableBase通知ListView何时类中的属性发生更改。它实现了INotifyPropertyChanged。如果你不熟悉它,你应该阅读XAML数据绑定。

并且,它还使用MyBgConverter(Laith定义)将bool值更改为不同的背景颜色。

最后,使用类上的IsMyAirport属性,您可能不需要单独的MyAirports字符串列表。我没有删除它,因为我不确定你是否用它来做别的事。但是,您在AirportListView_ItemClick中的逻辑可以更改为仅使用IsMyAirport bool而不是MyAirports列表。

答案 1 :(得分:-1)

创建一个转换器,将bool转换为SolidColorBrush并在绑定中使用该转换器。

<ListView Background="{x:Bind IsPartOfMyAirports, Converter={StaticResource MyBgConverter}}">
...
</ListView>

您的视图模型将负责通知IsPartOfMyAirports的更改。

您的转换器看起来像这样:

public class MyBgConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        var b = (bool)value;
        var color = b ? Colors.Yellow : Colors.Green;

        return new SolidColorBrush(color);
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        throw new NotImplementedException();
    }
}