视图:我有usercontrol,它具有文本框和标签。当“ Enter”键关闭时,我希望标签使用文本框的值表单更新。为了这个示例,我创建了一个CaruserControl。我将在MainWindow的ItemScontrol中托管这些列表。
模型:我有班车,这将是模型。
ViewModel:我没有Carusercontrol和汽车的ViewModel。我为MainWindow提供了一个 - 我们将其称为MainViewModel。
我可以从各个usercontrols到MainViewModel传播命令,但是我不确定从MainViewModel中的文本框中获取值吗?
以下是我从我在线阅读的有关MVVM的内容中做出的一些假设(当然有一些来源说假设是错误的)。
1] USERCONTROL不应具有ViewModel。
2] USERCONTROL只能揭示依赖性属性,而不应具有InotifyChanged或事件的公共属性。
因此,问题是,如何更新标签,并在MainViewModel中访问文本框值。
这是测试代码:
----- carusercontrol.xaml ----
<UserControl x:Class="TestMVVM.CarUserControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:TestMVVM" mc:Ignorable="d" d:DesignHeight="50" d:DesignWidth="300" x:Name="thisUC"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <Label Grid.Column="0">--</Label> <TextBox Grid.Column="1" Background="#FFE8D3D3" BorderThickness="0"> <TextBox.InputBindings> <KeyBinding Key="Enter" Command="{Binding KeyDownCommand, ElementName=thisUC}" CommandParameter="{Binding}"/> </TextBox.InputBindings> </TextBox> </Grid></UserControl>----- carusercontrol.cs -----------------
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows;using System.Windows.Controls;using System.Windows.Data;using System.Windows.Documents;using System.Windows.Input;using System.Windows.Media;using System.Windows.Media.Imaging;using System.Windows.Navigation;using System.Windows.Shapes;namespace TestMVVM{ /// <summary> /// Interaction logic for CarUserControl.xaml /// The Usercontrol /// </summary> public partial class CarUserControl : UserControl { private static readonly DependencyProperty StrValueProperty = DependencyProperty.Register("StrValue", typeof(float), typeof(CarUserControl), new PropertyMetadata(null)); private static readonly DependencyProperty KeyDownCommandProperty = DependencyProperty.Register("KeyDownCommand", typeof(ICommand), typeof(CarUserControl), new PropertyMetadata(null)); //Enter key down in the text box public CarUserControl() { InitializeComponent(); } public string StrValue { get { return (string)GetValue(StrValueProperty); } set { SetValue(StrValueProperty, value); } } /// <summary> /// "Enter" key down /// </summary> public ICommand KeyDownCommand { get { return (ICommand)GetValue(KeyDownCommandProperty); } set { SetValue(KeyDownCommandProperty, value); } } }}// ---型号 - car.cs
using System;using System.Collections.Generic;using System.ComponentModel;using System.Linq;using System.Text;using System.Threading.Tasks;namespace TestMVVM{ /// <summary> /// A simple model /// </summary> class Car : INotifyPropertyChanged { public Car(string name) { this.name = name; } private string name; public event PropertyChangedEventHandler PropertyChanged; public string Name { get { return name; } set { name = value; OnPropertyChanged("Name"); } } public void OnPropertyChanged(string name) { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) { handler(this, new PropertyChangedEventArgs(name)); } } }}-----主视图模型---
using System;using System.Collections.Generic;using System.Collections.ObjectModel;using System.ComponentModel;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows.Input;namespace TestMVVM{ /// <summary> /// The Main View Model /// </summary> class MainViewModel : INotifyPropertyChanged { /// <summary> /// The main view model /// </summary> public MainViewModel() { //Create some test data cars = new ObservableCollection<Car>(); cars.Add(new Car("Audi")); cars.Add(new Car("Toyota")); cars.Add(new Car("Subaru")); cars.Add(new Car("Volvo")); } public event PropertyChangedEventHandler PropertyChanged; private ObservableCollection<Car> cars; //List of tensioner spools private ICommand enterDownCommand; public ObservableCollection<Car> Cars { get { return cars; } set { cars = value; OnPropertyChanged("Cars"); } } public ICommand EnterDownCommand { get { if (enterDownCommand == null) { enterDownCommand = new RelayMCommand<Car>(OnEnterDownCommand); } return enterDownCommand; } } /// <summary> /// Called when "Enter" key is down. /// </summary> /// <param name="obj"></param> private void OnEnterDownCommand(Car obj) { //How do I get the text box value here? Console.Write(">>"+obj.Name); } public void OnPropertyChanged(string name) { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) { handler(this, new PropertyChangedEventArgs(name)); } } }}----- Mainwindow ---
<Window x:Class="TestMVVM.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:TestMVVM" mc:Ignorable="d" Title="MainWindow" Height="350" Width="525"> <Window.DataContext> <local:MainViewModel x:Name ="MainVM"/> </Window.DataContext> <Grid> <Grid.RowDefinitions> <RowDefinition Height="*"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <Grid Grid.Row="0"> <Viewbox> <ItemsControl ItemsSource="{Binding Cars}" Margin="5" Width="200"> <ItemsControl.ItemTemplate> <DataTemplate> <local:CarUserControl Margin="5" KeyDownCommand="{Binding Path=DataContext.EnterDownCommand, RelativeSource={RelativeSource AncestorType=ItemsControl}}"/> </DataTemplate> </ItemsControl.ItemTemplate> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <StackPanel Orientation="Vertical" IsItemsHost="True" /> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> </ItemsControl> </Viewbox> </Grid> </Grid></Window>---继电器命令---
using System;using System.Threading;using System.Windows.Input;namespace TestMVVM{ /// <summary> /// Same as the Relay Command, except this handles an array of generic type <T> /// </summary> /// <typeparam name="T">Generic type parameter</typeparam> public class RelayMCommand<T> : ICommand { private Predicate<T> _canExecute; private Action<T> _execute; public RelayMCommand(Action<T> execute, Predicate<T> canExecute = null) { _execute = execute; _canExecute = canExecute; } private void Execute(T parameter) { _execute(parameter); } private bool CanExecute(T parameter) { return _canExecute == null ? true : _canExecute(parameter); } public bool CanExecute(object parameter) { return parameter == null ? false : CanExecute((T)parameter); } public void Execute(object parameter) { _execute((T)parameter); } public event EventHandler CanExecuteChanged; public void RaiseCanExecuteChanged() { var temp = Volatile.Read(ref CanExecuteChanged); if (temp != null) { temp(this, new EventArgs()); } } }}一个 UserControl 可能会继承它 DataContext 从父窗口或当前项目 ItemsControl.
因此,如果您束缚您的 ItemsControl 到一个 IEnumerable<Car>,每个实例的 CarUserControl 可以直接与 Name 相应的属性 Car 目的:
<TextBox Text="{Binding Name}" Grid.Column="1" Background="#FFE8D3D3" BorderThickness="0"> <TextBox.InputBindings> <KeyBinding Key="Enter" Command="{Binding KeyDownCommand, ElementName=thisUC}" CommandParameter="{Binding}"/> </TextBox.InputBindings></TextBox>这是因为 UserControl 自动继承 DataContext 来自其父元素,这是相应的 Car 对象 ItemsControl 在这种情况下。
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah
我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以
我想从then子句中访问case语句表达式,即food="cheese"casefoodwhen"dip"then"carrotsticks"when"cheese"then"#{expr}crackers"else"mayo"end在这种情况下,expr是食物的当前值(value)。在这种情况下,我知道,我可以简单地访问变量food,但是在某些情况下,该值可能无法再访问(array.shift等)。除了将expr移出到局部变量然后访问它之外,是否有直接访问caseexpr值的方法?罗亚附注我知道这个具体示例很简单,只是一个示例场景。 最佳答案
我理解(我认为)Ruby中类变量和类的实例变量之间的区别。我想知道如何从该类外部访问该类的实例变量。从内部(即在类方法中而不是实例方法中),它可以直接访问,但是从外部,有没有办法做MyClass.class.[@$#]variablename?我没有任何具体原因要这样做,只是学习Ruby并想知道是否可行。 最佳答案 classMyClass@my_class_instance_var="foo"class上述yield:>>foo我相信Arkku演示了如何从类外部访问类变量(@@),而不是类实例变量(@)。我从这篇文章中提取了上述内
我试图在我的网站上实现使用Facebook登录功能,但在尝试从Facebook取回访问token时遇到障碍。这是我的代码:ifparams[:error_reason]=="user_denied"thenflash[:error]="TologinwithFacebook,youmustclick'Allow'toletthesiteaccessyourinformation"redirect_to:loginelsifparams[:code]thentoken_uri=URI.parse("https://graph.facebook.com/oauth/access_token
是否有可能以某种方式访问Class.new范围内的a?a=5Class.new{defb;aend}.new.b#NameError:undefinedlocalvariableormethod`a'for#:0x007fa8b15e9af0>#:in`b' 最佳答案 即使@MarekLipka的回答是正确的——改变变量范围总是有风险的。这是可行的,因为每个block都带有创建它的上下文,因此您的局部变量a突然变得不那么局部了——它变成了一个“隐藏的”全局变量:a=5object=Class.new{define_method(
使用散列定义的访问器方法动态创建对象的最简单方法是什么?例如,如果我有一个散列:{foo:"Foo",bar:"Bar"}我想要一个具有访问器方法foo、foo=、bar和bar=的对象,其初始值分别为"Foo"和"Bar"。我可以想到这样做:moduleObjectWithAccessordefself.newh;Struct.new(*h.keys).new(*h.values)endendo=ObjectWithAccessor.new(foo:"Foo",bar:"Bar")o.foo#=>"Foo"但是,我不需要它们的多个实例具有相同的特定键集,而是希望每次都使用可能不同的键
我在这方面尝试了很多URL,在我遇到这个特定的之前,它们似乎都很好:require'rubygems'require'nokogiri'require'open-uri'doc=Nokogiri::HTML(open("http://www.moxyst.com/fashion/men-clothing/underwear.html"))putsdoc这是结果:/Users/macbookair/.rvm/rubies/ruby-2.0.0-p481/lib/ruby/2.0.0/open-uri.rb:353:in`open_http':404NotFound(OpenURI::HT
我的Ruby-on-Rails项目中有以下文件结构,用于规范:/spec/msd/serviceservice_spec.rb/support/my_modulerequests_stubs.rb我的request_stubs.rb有:moduleMyModule::RequestsStubsmodule_functiondeflist_clientsurl="dummysite.com/clients"stub_request(:get,url).to_return(status:200,body:"clientsbody")endend在我的service_spec.rb我有:re