Xaml 在listview MVVM中绑定复选框

Xaml 在listview MVVM中绑定复选框,xaml,listview,windows-phone-8,mvvm,Xaml,Listview,Windows Phone 8,Mvvm,我正在尝试按如下方式绑定复选框,但当我单击它时,它甚至没有保持选中状态。下面是映射到db的我的模型。我希望使用选中的复选框获取所选项目,以便最终获取成本字段。我已尝试从 由Matt Baxter Reynolds和Iris Classon编写。我已更新代码以匹配@Arnaud提供的答案。复选框不会保持选中状态,但单击单选按钮时按钮的可见性会发生变化 型号服务项目 public class ServiceItem:ModelItem { // key field.

我正在尝试按如下方式绑定复选框,但当我单击它时,它甚至没有保持选中状态。下面是映射到db的我的模型。我希望使用选中的复选框获取所选项目,以便最终获取成本字段。我已尝试从 由Matt Baxter Reynolds和Iris Classon编写。我已更新代码以匹配@Arnaud提供的答案。复选框不会保持选中状态,但单击单选按钮时按钮的可见性会发生变化

型号服务项目

     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()
        {
        }
    }
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);
    }
}
视图模型接口Iviewmodel

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

    }

}
<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}" 
public abstract class ViewModel : ModelItem, IViewModel
    {
        //  somewhere to hold the host...
        protected IViewModelHost Host { get; private set; }
    //other code omitted
    }
 public interface IViewModel : INotifyPropertyChanged
    {
        void Initialize(IViewModelHost host);
    //other code omitted
    }
ModelItem

     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()
        {
        }
    }
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);
    }
}
公共抽象类ModelItem:INotifyPropertyChanged
{
专用字典值{get;set;}
受保护的模型项()
{
this.Values=newdictionary();
}
公共事件属性更改事件处理程序属性更改;
受保护的T GetValue([CallerMemberName]字符串名称=null)
{
if(this.Values.ContainsKey(name))
返回(T)this.Values[name];
其他的
返回默认值(T);
}
受保护的void SetValue(对象值,[CallerMemberName]字符串名称=null)
{
//设置。。。
this.Values[name]=值;
//通知。。。
此.OnPropertyChanged(新PropertyChangedEventArgs(名称));
}
受保护的void OnPropertyChanged([CallerMemberName]字符串名称=null)
{
此.OnPropertyChanged(新PropertyChangedEventArgs(名称));
}
PropertyChanged上受保护的虚拟无效(PropertyChangedEventArgs e)
{
if(this.PropertyChanged!=null)
本。财产变更(本,e);
}
}

您需要在类
ServiceItem
上实现
INotifyPropertyChanged
,否则在更新值时将永远不会引发任何事件

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

<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
上实现
INotifyPropertyChanged
,否则在更新值时将永远不会引发任何事件

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

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

我已经在接口IViewModel上更改了Inotifypropertychanged。为了完整起见,我添加它@AmaudYes,但您仍然需要在ViewModel使用的类上实现
Inotifypropertychanged
。ServicesPageViewModel实现了ViewModel,它实现了IViewModel,而IViewModel实现了InotifyPropertyChangedInes,但这还不够。例如,检查此模型类:。它扩展了
ModelItem
类,以便为以下属性实现
INotifyPropertyChanged
:Description和Active。我已在回答中更新了ServiceItem类以使用您的模型类。例如,活动属性声明为
public bool Active{get{return this.GetValue();}内部集{this.SetValue(value);}}
适用于阅读此内容并犯同样愚蠢错误的任何人。复选框中的复选框在白色背景上为白色,前景色设置为黑色只会使文本内容变为黑色,而不是勾号本身。#MyRookeeMissMakeS101我已在我的界面IViewModel上更改了InotifyProperty。为了完整性,我添加它@AmaudYes,但是您仍然需要在ViewModel使用的类上实现
INotifyPropertyChanged
。ServicesPageViewModel实现了ViewModel,后者实现了IViewModel,后者实现了InotifyPropertyChangedInes,但这还不够。例如,检查此模型类:。它扩展了
ModelItem
类,以便为以下属性实现
INotifyPropertyChanged
:Description和Active。我已在回答中更新了ServiceItem类以使用您的模型类。例如,活动属性声明为
public bool Active{get{return this.GetValue();}内部集{this.SetValue(value);}}
适用于阅读此内容并犯同样愚蠢错误的任何人。复选框中的复选框在白色背景上为白色,而前景色设置为黑色只会使文本内容变为黑色,而不会使勾号本身变为黑色。#MyRookie出错101