绑定listview MVVM中的复选框

时间:2016-06-20 10:38:26

标签: xaml listview windows-phone-8 mvvm

我正在尝试绑定复选框,如下所示但是当我点击它时它甚至不会保持检查。下面是我的模型,它映射到db.I想要使用选中的复选框获取所选项目所以我最终可以获取成本字段。我试图遵循Programming Windows Store Apps with C#.中的代码示例 作者:Matt Baxter-Reynolds和Iris Classon。我更新了我的代码,以匹配@ Arnaud提供的答案。复选框不会保持选中状态,但单击无线电按钮时按钮的可见性会发生变化。

Model ServiceItem

     public class ServiceItem:ModelItem
    {
        // key field...
        [AutoIncrement(), PrimaryKey(), JsonIgnore]
        public int Id { get; set; }

        // other fields...
        [Unique, JsonProperty("id")]
        public int NativeId { get; set; }
        [JsonProperty("name")]
        public string Name { get; set; }
        public decimal Cost
      {
        get
        {
            return GetValue<decimal>();
        }
        set
        {
            SetValue(value);
        }
      }
      [JsonIgnore] //prefer not to have it on db has no value
      public bool IsSelected
     {
        get
        {
            return GetValue<bool>();
        }
        set
        {
            SetValue(value);
        }
     }

        public ServiceItem()
        {
        }
    }

以下是Viewmodel

ServicesPage ViewModel

    public class ServicesPageViewModel : ViewModel, IServicesPageViewModel
{
    public ObservableCollection<ServiceItem> Items { get; private set; }

    public ICommand ContinueCommand { get; private set; }
    public ServicesPageViewModel()
    {
    }

    public override void Initialize(IViewModelHost host)
    {
        base.Initialize(host);
        // setup...
        this.Items = new ObservableCollection<ServiceItem>();

        this.ContinueCommand = new DelegateCommand((args) => GetSelected(args as CommandExecutionContext));

    }

}

下面是xaml 的 ServicePage.xaml

<ListView ItemsSource="{Binding Items}" 
                  IsItemClickEnabled="true"                      
                  Margin="10,10,10,0" TabIndex="1">                
            <ListView.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="3*"></ColumnDefinition>
                            <ColumnDefinition/>
                        </Grid.ColumnDefinitions>
                        <CheckBox Content="{Binding Name}"  
                                  BorderBrush="{ThemeResource AppBarBackgroundThemeBrush}"
                                  IsChecked="{Binding IsSelected, Mode=TwoWay}"></CheckBox>
                        <Button Content="{Binding Cost, Mode=TwoWay}" 

Visibility =&#34; {Binding IsSelected,Converter = {StaticResource BooleanToVisibilityConverter}}&#34; Grid.Column =&#34; 1&#34;&GT;                                                                            

视图模型

public abstract class ViewModel : ModelItem, IViewModel
    {
        //  somewhere to hold the host...
        protected IViewModelHost Host { get; private set; }
    //other code omitted
    }

Viewmodel界面Iviewmodel

 public interface IViewModel : INotifyPropertyChanged
    {
        void Initialize(IViewModelHost host);
    //other code omitted
    }

ModelItem

public abstract class ModelItem : INotifyPropertyChanged
{
    private Dictionary<string, object> Values { get; set; }

    protected ModelItem()
    {
        this.Values = new Dictionary<string, object>();
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected T GetValue<T>([CallerMemberName] string name = null)
    {
        if (this.Values.ContainsKey(name))
            return (T)this.Values[name];
        else
            return default(T);
    }

    protected void SetValue(object value, [CallerMemberName] string name = null)
    {
        // set...
        this.Values[name] = value;

        // notify...
        this.OnPropertyChanged(new PropertyChangedEventArgs(name));
    }

    protected void OnPropertyChanged([CallerMemberName] string name = null)
    {
        this.OnPropertyChanged(new PropertyChangedEventArgs(name));
    }

    protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
    {
        if (this.PropertyChanged != null)
            this.PropertyChanged(this, e);
    }
}

1 个答案:

答案 0 :(得分:1)

您需要在班级INotifyPropertyChanged上实施ServiceItem,否则在更新该值时,您绝不会提出任何事件。

以下是我的观点代码。我添加了一个转换器,仅在选择项目时显示成本:

<Page
    x:Class="App4.CheckBoxPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App4"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    DataContext="{Binding RelativeSource={RelativeSource Self}}"
    >
    <Page.Resources>
        <local:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
    </Page.Resources>
    <ListView ItemsSource="{Binding Items}" 
                  IsItemClickEnabled="true"                      
                  Margin="10,10,10,0" TabIndex="1">
        <ListView.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="3*"></ColumnDefinition>
                        <ColumnDefinition/>
                    </Grid.ColumnDefinitions>
                    <CheckBox Content="{Binding Name}"  
                                  BorderBrush="{ThemeResource AppBarBackgroundThemeBrush}"
                                  IsChecked="{Binding IsSelected, Mode=TwoWay}"></CheckBox>
                    <Button Content="{Binding Cost, Mode=TwoWay}" Visibility="{Binding IsSelected, Converter={StaticResource BooleanToVisibilityConverter}}" Grid.Column="1"></Button>
                </Grid>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</Page>

我使用过的课程。 ServiceItem需要扩展ModelItem,以便通知视图 Cost IsSelected 的属性更改。如果没有它,View将只获取 Cost IsSelected 的初始值,View将忽略这些属性的所有更新。

public sealed partial class CheckBoxPage : Page
{
    public CheckBoxPage()
    {
        var items = new ObservableCollection<ServiceItem>()
        {
            new ServiceItem() {Name = "Item 1", Id = 1, NativeId = 1, Cost = 123 },
            new ServiceItem() {Name = "Item 2", Id = 2, NativeId = 2, Cost = 456 },
            new ServiceItem() {Name = "Item 3", Id = 3, NativeId = 3, Cost = 789 },
            new ServiceItem() {Name = "Item 4", Id = 4, NativeId = 4, Cost = 1011 },
        };

        Items = items;

        this.InitializeComponent();
    }

    public ObservableCollection<ServiceItem> Items
    {
        get;
        set;
    }
}

public class ServiceItem : ModelItem
{
    public int Id { get; set; }
    public int NativeId { get; set; }
    public string Name { get; set; }

    public decimal Cost {
        get
        {
            return GetValue<decimal>();
        }
        set
        {
            SetValue(value);
        }
    }

    public bool IsSelected
    {
        get
        {
            return GetValue<bool>();
        }
        set
        {
            SetValue(value);
        }
    }
}