C# x:将ListView中的项绑定到ViewModel

C# x:将ListView中的项绑定到ViewModel,c#,listview,uwp,C#,Listview,Uwp,你知道,当你盯着某件事看得够久的时候,它就不再有意义了。。。我试图将listview项的background属性绑定到它是否是viewmodel中集合的一部分。以下是我正在使用的简化版本: <Grid> <ListView x:Name="AirportListView" SelectionMode="None" IsItemClickEnabled="True" ItemClick=

你知道,当你盯着某件事看得够久的时候,它就不再有意义了。。。我试图将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>

以及:

公共密封部分类主页面:第页
{
公共ObservableCollection MyAirports{get;set;}=new ObservableCollection();
公共主页()
{
this.InitializeComponent();
AirportListView.ItemsSource=新列表()
{
“EDDB”,
“LGIR”,
“艾哈姆”,
“LFPO”,
“EGKK”
};
}
private void AirportListView_ItemClick(对象发送者,ItemClickEventArgs e)
{
如果(例如ClickedItem是字符串clickedAirport)
{
if(MyAirports.Contains(单击机场))
我的机场。删除(单击机场);
其他的
MyAirports.Add(单击机场);
}
}
}
理想情况下,我希望实现的是在datatemplate中绑定网格的背景,以便当项目是MyAirports的一部分时,它是不同的颜色。我只是不知道如何使用x:Bind或Binding来实现这一点。我可以想出一些更冗长的方法来实现同样的目标,但我想知道是否有一种更优雅的数据绑定解决方案

任何想法都将不胜感激


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

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

您需要使到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); }
    }
}
公共密封部分类AirportListView:第页
{
公共ObservableCollection MyAirports{get;set;}=new ObservableCollection();
公共可观测收集机场{get;set;}
公共机场列表视图()
{
this.InitializeComponent();
机场=新的可观测集合
{
新的AirportItem{Name=“EDDB”},
新的AirportItem{Name=“LGIR”},
新的AirportItem{Name=“LFPO”},
新机场项目{Name=“EGKK”}
};
}
private void AirportListView_ItemClick(对象发送者,ItemClickEventArgs e)
{
如果(如ClickedItem是AirportItem clickedAirport)
{
if(MyAirports.Contains(clickedAirport.Name))
{
MyAirports.Remove(单击机场名称);
单击eDairport.IsMyAirport=false;
}
其他的
{
添加(单击机场名称);
单击edairport.IsMyAirport=true;
}
}
}
}
公共类AirportItem:BindableBase
{
私有字符串\u名称;
公共字符串名
{
获取{return\u name;}
set{SetProperty(ref_name,value);}
}
private bool_isMyAirport=false;
公共图书馆伊斯梅尔机场
{
获取{return\u isMyAirport;}
set{SetProperty(ref_isMyAirport,value);}
}
}
AirportItem使用BindableBase通知ListView类中的属性何时更改。它实现INotifyPropertyChanged。如果您不熟悉它,您应该阅读XAML数据绑定

而且,它还使用MyBgConverter(Laith定义的)将布尔值更改为不同的背景色


最后,使用类上的IsMyAirport属性,您可能不需要单独的MyAirports字符串列表。我没有移除它,因为我不确定你是否在用它做其他用途。但是您在AirportListView\u ItemClick中的逻辑可以更改为只使用IsMyAirportBool而不是MyAirports列表。

Hi-Laith,谢谢您的建议。我们的想法是绑定每个项目的背景,因此我不确定在哪里创建
IsPartOfMyAirports
,以便每个项目都可以更新。谢谢Pedro,是的,这是我实际尝试的简化版本,但是,正如您所说,我已经成功地将一个名为IsMyAirport的属性“烘焙”到原始类中,并确保该属性随着集合的更改而保持更新。现在,我将尝试让它在我的应用程序中工作。非常感谢!
<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); }
    }
}