C# 使用MVVM在Windows Phone 8.1应用程序上进行双向绑定
我正在使用MVVM开发一个销售管理系统,但在保存视图中输入的数据时遇到问题。我假设双向绑定意味着在视图上输入的所有值都应该传递给ViewModel,反之亦然,对吗 查看:C# 使用MVVM在Windows Phone 8.1应用程序上进行双向绑定,c#,xaml,mvvm,binding,windows-phone-8.1,C#,Xaml,Mvvm,Binding,Windows Phone 8.1,我正在使用MVVM开发一个销售管理系统,但在保存视图中输入的数据时遇到问题。我假设双向绑定意味着在视图上输入的所有值都应该传递给ViewModel,反之亦然,对吗 查看: <TextBox x:Name="NameText" Grid.ColumnSpan="2" Grid.Row="2" Header="Nombre:" Style="{StaticResource Register
<TextBox x:Name="NameText"
Grid.ColumnSpan="2"
Grid.Row="2"
Header="Nombre:"
Style="{StaticResource RegisterTextBoxStyle}"
Text="{Binding Product.Name, Mode=TwoWay}"/>
<ComboBox x:Name="UnitCombo"
Grid.Row="3"
Grid.ColumnSpan="2"
Header="Unidad:"
PlaceholderText="Elige la medida"
Style="{StaticResource RegisterComboBoxStyle}"
ItemsSource="{Binding Path=UnitsSource, Mode=OneWay}"
SelectedValue="{Binding SelectedUnit, Mode=TwoWay}"/>
<TextBox x:Name="CostText"
Grid.Column="0"
Grid.Row="4"
Header="Costo:"
Style="{StaticResource RegisterTextBoxStyle}"
Text="{Binding Product.Cost, Mode=TwoWay}"/>
<TextBox x:Name="PriceText"
Grid.Column="1"
Grid.Row="4"
Header="Precio:"
Style="{StaticResource RegisterTextBoxStyle}"
Text="{Binding Product.Price, Mode=TwoWay}"/>
<ToggleSwitch x:Name="ActiveToggle"
Grid.Column="1"
Grid.Row="5"
Style="{StaticResource RegisterToggleSwithStyle}"
IsOn="{Binding Product.Active, Mode=TwoWay}"/>
namespace BillingShop.ViewModel
{
public class ProductListViewModel : ViewModelBase, INavigable
{
public ObservableCollection<ProductViewModel> Items { get; private set; }
private DelegateCommand _saveProduct;
public bool IsUpdating { get; set; }
public ProductViewModel Product { get; set; }
public Visibility UpdatingVisibility => (IsUpdating || Items == null || Items.Count == 0) ? Visibility.Visible : Visibility.Collapsed;
public ProductListViewModel()
{
if (IsInDesignMode)
{
return;
}
_saveProduct = new DelegateCommand(SaveCommand_Executed);
}
#region Product Members
private string _unit;
public string SelectedUnit
{
get { return _unit; }
set
{
_unit = value;
OnPropertyChanged();
}
}
#endregion
public IEnumerable<RegisteredUnits> UnitsSource => Enum.GetValues(typeof(RegisteredUnits)).Cast<RegisteredUnits>();
public ICommand SaveCommand => _saveProduct;
private void SaveCommand_Executed()
{
var product = new Product
{
Name = Product.Name,
Unit = Product.Unit,
Cost = Convert.ToDouble(Product.Cost),
Price = Convert.ToDouble(Product.Price),
Active = Convert.ToBoolean(Product.Active)
};
ProductManager.SaveProduct(product);
}
public void PopulateProductViewModel(ProductViewModel entry)
{
Product = entry;
OnPropertyChanged("Product");
}
public Product GetProduct()
{
return Product?.GetProduct();
}
}
public class ProductViewModel : ViewModelBase
{
public int Id { get; set; }
public string Name { get; set; }
public string Unit { get; set; }
public double Cost { get; set; }
public double Price { get; set; }
public bool Active { get; set; }
public List<SalesDetails> SalesDetail { get; set; }
public ProductViewModel()
{
}
public ProductViewModel(Product item)
{
Update(item);
}
public void Update (Product item)
{
Id = item.ID;
Name = item.Name;
Unit = item.Unit;
Cost = item.Cost;
Price = item.Price;
Active = item.Active;
SalesDetail = item.SalesDetail;
}
public Product GetProduct()
{
return new Product
{
ID = Id,
Name = Name,
Unit = Unit,
Cost = Cost,
Price = Price,
Active = Active,
SalesDetail = SalesDetail
};
}
}
public class Product : IBusinessEntity
{
/// <summary>
/// Represents a Product.
/// </summary>
public Product()
{
}
/// <summary>
/// Get or sets the product identifier.
/// </summary>
[PrimaryKey, AutoIncrement]
public int ID { get; set; }
/// <summary>
/// Get or sets the product name.
/// </summary>
[MaxLength(40)]
public string Name { get; set; }
/// <summary>
/// Get or sets if the product can be measured in units or kilograms.
/// </summary>
public string Unit { get; set; }
/// <summary>
/// Get or sets the product cost.
/// </summary>
public double Cost { get; set; }
/// <summary>
/// Get or sets the product price.
/// </summary>
public double Price { get; set; }
/// <summary>
/// Get or sets the product state.
/// </summary>
public bool Active { get; set; }
/// <summary>
/// One-To-Many relationship with SalesDetails.
/// </summary>
[OneToMany(CascadeOperations = CascadeOperation.All)]
public List<SalesDetails> SalesDetail { get; set; }
}
ProductListViewModel:
<TextBox x:Name="NameText"
Grid.ColumnSpan="2"
Grid.Row="2"
Header="Nombre:"
Style="{StaticResource RegisterTextBoxStyle}"
Text="{Binding Product.Name, Mode=TwoWay}"/>
<ComboBox x:Name="UnitCombo"
Grid.Row="3"
Grid.ColumnSpan="2"
Header="Unidad:"
PlaceholderText="Elige la medida"
Style="{StaticResource RegisterComboBoxStyle}"
ItemsSource="{Binding Path=UnitsSource, Mode=OneWay}"
SelectedValue="{Binding SelectedUnit, Mode=TwoWay}"/>
<TextBox x:Name="CostText"
Grid.Column="0"
Grid.Row="4"
Header="Costo:"
Style="{StaticResource RegisterTextBoxStyle}"
Text="{Binding Product.Cost, Mode=TwoWay}"/>
<TextBox x:Name="PriceText"
Grid.Column="1"
Grid.Row="4"
Header="Precio:"
Style="{StaticResource RegisterTextBoxStyle}"
Text="{Binding Product.Price, Mode=TwoWay}"/>
<ToggleSwitch x:Name="ActiveToggle"
Grid.Column="1"
Grid.Row="5"
Style="{StaticResource RegisterToggleSwithStyle}"
IsOn="{Binding Product.Active, Mode=TwoWay}"/>
namespace BillingShop.ViewModel
{
public class ProductListViewModel : ViewModelBase, INavigable
{
public ObservableCollection<ProductViewModel> Items { get; private set; }
private DelegateCommand _saveProduct;
public bool IsUpdating { get; set; }
public ProductViewModel Product { get; set; }
public Visibility UpdatingVisibility => (IsUpdating || Items == null || Items.Count == 0) ? Visibility.Visible : Visibility.Collapsed;
public ProductListViewModel()
{
if (IsInDesignMode)
{
return;
}
_saveProduct = new DelegateCommand(SaveCommand_Executed);
}
#region Product Members
private string _unit;
public string SelectedUnit
{
get { return _unit; }
set
{
_unit = value;
OnPropertyChanged();
}
}
#endregion
public IEnumerable<RegisteredUnits> UnitsSource => Enum.GetValues(typeof(RegisteredUnits)).Cast<RegisteredUnits>();
public ICommand SaveCommand => _saveProduct;
private void SaveCommand_Executed()
{
var product = new Product
{
Name = Product.Name,
Unit = Product.Unit,
Cost = Convert.ToDouble(Product.Cost),
Price = Convert.ToDouble(Product.Price),
Active = Convert.ToBoolean(Product.Active)
};
ProductManager.SaveProduct(product);
}
public void PopulateProductViewModel(ProductViewModel entry)
{
Product = entry;
OnPropertyChanged("Product");
}
public Product GetProduct()
{
return Product?.GetProduct();
}
}
public class ProductViewModel : ViewModelBase
{
public int Id { get; set; }
public string Name { get; set; }
public string Unit { get; set; }
public double Cost { get; set; }
public double Price { get; set; }
public bool Active { get; set; }
public List<SalesDetails> SalesDetail { get; set; }
public ProductViewModel()
{
}
public ProductViewModel(Product item)
{
Update(item);
}
public void Update (Product item)
{
Id = item.ID;
Name = item.Name;
Unit = item.Unit;
Cost = item.Cost;
Price = item.Price;
Active = item.Active;
SalesDetail = item.SalesDetail;
}
public Product GetProduct()
{
return new Product
{
ID = Id,
Name = Name,
Unit = Unit,
Cost = Cost,
Price = Price,
Active = Active,
SalesDetail = SalesDetail
};
}
}
public class Product : IBusinessEntity
{
/// <summary>
/// Represents a Product.
/// </summary>
public Product()
{
}
/// <summary>
/// Get or sets the product identifier.
/// </summary>
[PrimaryKey, AutoIncrement]
public int ID { get; set; }
/// <summary>
/// Get or sets the product name.
/// </summary>
[MaxLength(40)]
public string Name { get; set; }
/// <summary>
/// Get or sets if the product can be measured in units or kilograms.
/// </summary>
public string Unit { get; set; }
/// <summary>
/// Get or sets the product cost.
/// </summary>
public double Cost { get; set; }
/// <summary>
/// Get or sets the product price.
/// </summary>
public double Price { get; set; }
/// <summary>
/// Get or sets the product state.
/// </summary>
public bool Active { get; set; }
/// <summary>
/// One-To-Many relationship with SalesDetails.
/// </summary>
[OneToMany(CascadeOperations = CascadeOperation.All)]
public List<SalesDetails> SalesDetail { get; set; }
}
namespace BillingShop.ViewModel
{
公共类ProductListViewModel:ViewModelBase,不可用
{
公共可观测集合项{get;private set;}
私有DelegateCommand_saveProduct;
公共bool正在更新{get;set;}
公共产品视图模型产品{get;set;}
公共可见性更新可见性=>(IsUpdate | | Items==null | | Items.Count==0)?可见性。可见:可见性。折叠;
公共产品列表视图模型()
{
如果(IsInDesignMode)
{
返回;
}
_saveProduct=新的DelegateCommand(SaveCommand_已执行);
}
#地区产品成员
专用字符串单元;
公共字符串SelectedUnit
{
获取{return\u unit;}
设置
{
_单位=价值;
OnPropertyChanged();
}
}
#端区
public IEnumerable UnitsSource=>Enum.GetValues(typeof(RegisteredUnits)).Cast();
公共ICommand SaveCommand=>\u saveProduct;
私有void SaveCommand_Executed()
{
var产品=新产品
{
Name=Product.Name,
单位=产品单位,
成本=换算成双倍(产品成本),
价格=转换为双倍(产品价格),
Active=Convert.ToBoolean(Product.Active)
};
ProductManager.SaveProduct(产品);
}
public void PopulateProductViewModel(ProductViewModel条目)
{
产品=入口;
不动产变更(“产品”);
}
公共产品
{
退货产品?.GetProduct();
}
}
}
产品视图模型:
<TextBox x:Name="NameText"
Grid.ColumnSpan="2"
Grid.Row="2"
Header="Nombre:"
Style="{StaticResource RegisterTextBoxStyle}"
Text="{Binding Product.Name, Mode=TwoWay}"/>
<ComboBox x:Name="UnitCombo"
Grid.Row="3"
Grid.ColumnSpan="2"
Header="Unidad:"
PlaceholderText="Elige la medida"
Style="{StaticResource RegisterComboBoxStyle}"
ItemsSource="{Binding Path=UnitsSource, Mode=OneWay}"
SelectedValue="{Binding SelectedUnit, Mode=TwoWay}"/>
<TextBox x:Name="CostText"
Grid.Column="0"
Grid.Row="4"
Header="Costo:"
Style="{StaticResource RegisterTextBoxStyle}"
Text="{Binding Product.Cost, Mode=TwoWay}"/>
<TextBox x:Name="PriceText"
Grid.Column="1"
Grid.Row="4"
Header="Precio:"
Style="{StaticResource RegisterTextBoxStyle}"
Text="{Binding Product.Price, Mode=TwoWay}"/>
<ToggleSwitch x:Name="ActiveToggle"
Grid.Column="1"
Grid.Row="5"
Style="{StaticResource RegisterToggleSwithStyle}"
IsOn="{Binding Product.Active, Mode=TwoWay}"/>
namespace BillingShop.ViewModel
{
public class ProductListViewModel : ViewModelBase, INavigable
{
public ObservableCollection<ProductViewModel> Items { get; private set; }
private DelegateCommand _saveProduct;
public bool IsUpdating { get; set; }
public ProductViewModel Product { get; set; }
public Visibility UpdatingVisibility => (IsUpdating || Items == null || Items.Count == 0) ? Visibility.Visible : Visibility.Collapsed;
public ProductListViewModel()
{
if (IsInDesignMode)
{
return;
}
_saveProduct = new DelegateCommand(SaveCommand_Executed);
}
#region Product Members
private string _unit;
public string SelectedUnit
{
get { return _unit; }
set
{
_unit = value;
OnPropertyChanged();
}
}
#endregion
public IEnumerable<RegisteredUnits> UnitsSource => Enum.GetValues(typeof(RegisteredUnits)).Cast<RegisteredUnits>();
public ICommand SaveCommand => _saveProduct;
private void SaveCommand_Executed()
{
var product = new Product
{
Name = Product.Name,
Unit = Product.Unit,
Cost = Convert.ToDouble(Product.Cost),
Price = Convert.ToDouble(Product.Price),
Active = Convert.ToBoolean(Product.Active)
};
ProductManager.SaveProduct(product);
}
public void PopulateProductViewModel(ProductViewModel entry)
{
Product = entry;
OnPropertyChanged("Product");
}
public Product GetProduct()
{
return Product?.GetProduct();
}
}
public class ProductViewModel : ViewModelBase
{
public int Id { get; set; }
public string Name { get; set; }
public string Unit { get; set; }
public double Cost { get; set; }
public double Price { get; set; }
public bool Active { get; set; }
public List<SalesDetails> SalesDetail { get; set; }
public ProductViewModel()
{
}
public ProductViewModel(Product item)
{
Update(item);
}
public void Update (Product item)
{
Id = item.ID;
Name = item.Name;
Unit = item.Unit;
Cost = item.Cost;
Price = item.Price;
Active = item.Active;
SalesDetail = item.SalesDetail;
}
public Product GetProduct()
{
return new Product
{
ID = Id,
Name = Name,
Unit = Unit,
Cost = Cost,
Price = Price,
Active = Active,
SalesDetail = SalesDetail
};
}
}
public class Product : IBusinessEntity
{
/// <summary>
/// Represents a Product.
/// </summary>
public Product()
{
}
/// <summary>
/// Get or sets the product identifier.
/// </summary>
[PrimaryKey, AutoIncrement]
public int ID { get; set; }
/// <summary>
/// Get or sets the product name.
/// </summary>
[MaxLength(40)]
public string Name { get; set; }
/// <summary>
/// Get or sets if the product can be measured in units or kilograms.
/// </summary>
public string Unit { get; set; }
/// <summary>
/// Get or sets the product cost.
/// </summary>
public double Cost { get; set; }
/// <summary>
/// Get or sets the product price.
/// </summary>
public double Price { get; set; }
/// <summary>
/// Get or sets the product state.
/// </summary>
public bool Active { get; set; }
/// <summary>
/// One-To-Many relationship with SalesDetails.
/// </summary>
[OneToMany(CascadeOperations = CascadeOperation.All)]
public List<SalesDetails> SalesDetail { get; set; }
}
公共类ProductViewModel:ViewModelBase
{
公共int Id{get;set;}
公共字符串名称{get;set;}
公共字符串单元{get;set;}
公共双成本{get;set;}
公共双价{get;set;}
公共bool活动{get;set;}
公共列表SalesDetail{get;set;}
公共产品视图模型()
{
}
公共产品视图模型(产品项)
{
更新(项目);
}
公共作废更新(产品项)
{
Id=item.Id;
名称=项目名称;
单位=项目。单位;
成本=项目成本;
价格=项目价格;
活动=项目。活动;
SalesDetail=item.SalesDetail;
}
公共产品
{
退回新产品
{
ID=ID,
Name=Name,
单位=单位,
成本=成本,
价格=价格,
活动=活动,
SalesDetail=SalesDetail
};
}
}
执行SaveProduct时,Product类显示为null,那么我的视图值呢?我的代码有什么问题
感谢所有帮助我的人,我将我的存储库链接放在这里,也许有人想深入了解我的代码:
编辑:这是我的产品类别:
<TextBox x:Name="NameText"
Grid.ColumnSpan="2"
Grid.Row="2"
Header="Nombre:"
Style="{StaticResource RegisterTextBoxStyle}"
Text="{Binding Product.Name, Mode=TwoWay}"/>
<ComboBox x:Name="UnitCombo"
Grid.Row="3"
Grid.ColumnSpan="2"
Header="Unidad:"
PlaceholderText="Elige la medida"
Style="{StaticResource RegisterComboBoxStyle}"
ItemsSource="{Binding Path=UnitsSource, Mode=OneWay}"
SelectedValue="{Binding SelectedUnit, Mode=TwoWay}"/>
<TextBox x:Name="CostText"
Grid.Column="0"
Grid.Row="4"
Header="Costo:"
Style="{StaticResource RegisterTextBoxStyle}"
Text="{Binding Product.Cost, Mode=TwoWay}"/>
<TextBox x:Name="PriceText"
Grid.Column="1"
Grid.Row="4"
Header="Precio:"
Style="{StaticResource RegisterTextBoxStyle}"
Text="{Binding Product.Price, Mode=TwoWay}"/>
<ToggleSwitch x:Name="ActiveToggle"
Grid.Column="1"
Grid.Row="5"
Style="{StaticResource RegisterToggleSwithStyle}"
IsOn="{Binding Product.Active, Mode=TwoWay}"/>
namespace BillingShop.ViewModel
{
public class ProductListViewModel : ViewModelBase, INavigable
{
public ObservableCollection<ProductViewModel> Items { get; private set; }
private DelegateCommand _saveProduct;
public bool IsUpdating { get; set; }
public ProductViewModel Product { get; set; }
public Visibility UpdatingVisibility => (IsUpdating || Items == null || Items.Count == 0) ? Visibility.Visible : Visibility.Collapsed;
public ProductListViewModel()
{
if (IsInDesignMode)
{
return;
}
_saveProduct = new DelegateCommand(SaveCommand_Executed);
}
#region Product Members
private string _unit;
public string SelectedUnit
{
get { return _unit; }
set
{
_unit = value;
OnPropertyChanged();
}
}
#endregion
public IEnumerable<RegisteredUnits> UnitsSource => Enum.GetValues(typeof(RegisteredUnits)).Cast<RegisteredUnits>();
public ICommand SaveCommand => _saveProduct;
private void SaveCommand_Executed()
{
var product = new Product
{
Name = Product.Name,
Unit = Product.Unit,
Cost = Convert.ToDouble(Product.Cost),
Price = Convert.ToDouble(Product.Price),
Active = Convert.ToBoolean(Product.Active)
};
ProductManager.SaveProduct(product);
}
public void PopulateProductViewModel(ProductViewModel entry)
{
Product = entry;
OnPropertyChanged("Product");
}
public Product GetProduct()
{
return Product?.GetProduct();
}
}
public class ProductViewModel : ViewModelBase
{
public int Id { get; set; }
public string Name { get; set; }
public string Unit { get; set; }
public double Cost { get; set; }
public double Price { get; set; }
public bool Active { get; set; }
public List<SalesDetails> SalesDetail { get; set; }
public ProductViewModel()
{
}
public ProductViewModel(Product item)
{
Update(item);
}
public void Update (Product item)
{
Id = item.ID;
Name = item.Name;
Unit = item.Unit;
Cost = item.Cost;
Price = item.Price;
Active = item.Active;
SalesDetail = item.SalesDetail;
}
public Product GetProduct()
{
return new Product
{
ID = Id,
Name = Name,
Unit = Unit,
Cost = Cost,
Price = Price,
Active = Active,
SalesDetail = SalesDetail
};
}
}
public class Product : IBusinessEntity
{
/// <summary>
/// Represents a Product.
/// </summary>
public Product()
{
}
/// <summary>
/// Get or sets the product identifier.
/// </summary>
[PrimaryKey, AutoIncrement]
public int ID { get; set; }
/// <summary>
/// Get or sets the product name.
/// </summary>
[MaxLength(40)]
public string Name { get; set; }
/// <summary>
/// Get or sets if the product can be measured in units or kilograms.
/// </summary>
public string Unit { get; set; }
/// <summary>
/// Get or sets the product cost.
/// </summary>
public double Cost { get; set; }
/// <summary>
/// Get or sets the product price.
/// </summary>
public double Price { get; set; }
/// <summary>
/// Get or sets the product state.
/// </summary>
public bool Active { get; set; }
/// <summary>
/// One-To-Many relationship with SalesDetails.
/// </summary>
[OneToMany(CascadeOperations = CascadeOperation.All)]
public List<SalesDetails> SalesDetail { get; set; }
}
公共类产品:IBusinessEntity
{
///
///代表一种产品。
///
公共产品()
{
}
///
///获取或设置产品标识符。
///
[主密钥,自动增量]
公共int ID{get;set;}
///
///获取或设置产品名称。
///
[MaxLength(40)]
公共字符串名称{get;set;}
///
///获取或设置产品是否可以单位或千克计量。
///
公共字符串单元{get;set;}
///
///获取或设置产品成本。
///
公共双成本{get;set;}
///
///获取或设置产品价格。
///
公共双价{get;set;}
///
///获取或设置产品状态。
///
公共bool活动{get;set;}
///
///与SalesDetails的一对多关系。
///
[OneToMany(级联操作=级联操作.All)]
公共列表SalesDetail{get;set;}
}
解决方案是在ProductListViewModel构造函数内初始化产品属性:
public class ProductListViewModel
{
public ProductListViewModel ()
{
Product = new ProductViewModel();
}
.
.
.
}
感谢魏玛·亚米特·莫雷诺·佩雷斯的帮助,以及阿尔卡纳的干预。解决方案是在ProductListViewModel构造函数中初始化产品属性:
public class ProductListViewModel
{
public ProductListViewModel ()
{
Product = new ProductViewModel();
}
.
.
.
}
感谢魏玛·亚米特·莫雷诺·佩雷斯(Weimar Yamit Moreno Perez)的帮助,感谢阿尔卡纳(Archana)的干预。您在哪里创建产品类对象?除非实例化,否则它将为null。双向绑定的作用是在视图和viewmodel中填充名称、成本等属性。但是我猜你的产品对象本身是空的,它将如何填充它的属性呢?谢谢@Archana,我编辑了我的问题来添加这个类,它在BusinessLayer名称空间中,当我获得产品时没有任何问题,但是当我尝试设置值时,它会让人沮丧。有什么想法吗?没有,我问过你在ProductListViewModel中的何处以及如何创建Product对象?@Archana你的意思是这行:public ProductViewModel Product{get;set;}?是的。这就是声明,对吗?您在哪里创建产品类对象?除非实例化,否则它将为null。双向绑定的作用是在视图和viewmodel中填充名称、成本等属性。但是我猜你的产品对象本身是空的,它将如何填充它的属性呢?谢谢@Archana,我编辑了我的问题来添加这个类,它在BusinessLayer名称空间中,当我获得产品时没有任何问题,但是当我尝试设置值时,它会让人沮丧。有什么想法吗?没有,我问过你在ProductListViewModel中在哪里以及如何创建Product对象?@Archana你是说这个吗