5

我是 MVVM 的新手。我试图创建一个简单的程序,但遇到了一个问题。我创建了一个TokensViewModel和一个页面。但是绑定控件后我发现我的执行没有去TokensViewModel。请告诉我哪里出错了。以下是详细信息:

文件夹层次结构是这样的:

BusinessLogicLayer\TokenManager.cs

Commom\RelayCommand.cs

PresentationLayer\ViewModel\TokensViewModel.cs

PresentationLayer\Views\GenerateToken.xaml(页面)

ResourceAccessLayer\TokenRepository.cs

中继命令.cs:

class RelayCommand:ICommand
{
    readonly Action<object> _execute;
    readonly Predicate<object> _canExecute;
    public RelayCommand() { }
    public RelayCommand(Action<object> execute, Predicate<object> canExecute)
    {
        _execute = execute;
        _canExecute = canExecute;
    }

    public RelayCommand(Action<object> execute): this(execute, null) {}

    public bool CanExecute(object parameter)
    {
        return _canExecute==null?true:_canExecute(parameter);
    }
    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove{CommandManager.RequerySuggested-=value;}
    }
    public void Execute(object parameter)
    {
        _execute(parameter);
    }
}

令牌管理器.cs

class TokenManager
{
    public bool Add(token tokens)
    {
        return true;
    }        
}

生成令牌.xaml

<Page x:Class="xyz.GenerateToken"
  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" 
  mc:Ignorable="d" d:DesignHeight="800" d:DesignWidth="900"
  xmlns:ViewModels="clr-namespace:xyz.PresentationLayer.ViewModel"
  Title="GenerateToken">
  <Grid Height="750" Width="800">
    <TextBlock Height="23" HorizontalAlignment="Left" Margin="29,85,0,0" Name="lblName" Text="Name" VerticalAlignment="Top" FontSize="16" />
    <TextBlock FontSize="16" Height="23" HorizontalAlignment="Left" Margin="29,154,0,0" Name="lblPlateNumber" Text="Plate Number" VerticalAlignment="Top" />
    <TextBlock FontSize="16" Height="23" HorizontalAlignment="Left" Margin="29,226,0,0" Name="lblPancard" Text="Pancard Number" VerticalAlignment="Top" />
    <TextBlock FontSize="16" Height="23" HorizontalAlignment="Left" Margin="410,85,0,0" Name="lblContactNumber" Text="Contact Number" VerticalAlignment="Top" />
    <TextBlock FontSize="16" Height="23" HorizontalAlignment="Left" Margin="410,163,0,0" Name="lblAddres" Text="Address" VerticalAlignment="Top" Width="60" />
    <Button Content="Generate" Command="{Binding SaveCommand}"  Height="34" HorizontalAlignment="Left" Margin="216,328,0,0" Name="btnGenerateToken" VerticalAlignment="Top" Width="133" FontSize="20" />
    <TextBox Height="32" HorizontalAlignment="Left" Margin="178,85,0,0" Text="{Binding Path=Name}" Name="txtName" VerticalAlignment="Top" Width="186" BorderThickness="2" FontSize="16" />
    <TextBox BorderThickness="2" Height="32" HorizontalAlignment="Left" Text="{Binding Path=PlateNumber}" Margin="178,154,0,0" Name="txtPlateNumber" VerticalAlignment="Top" Width="186" FontSize="16" />
    <TextBox BorderThickness="2" Height="32" HorizontalAlignment="Left" Text="{Binding Path=PanNumber}" Margin="178,226,0,0" Name="txtPanNumber" VerticalAlignment="Top" Width="186" FontSize="16" />
    <TextBox BorderThickness="2" Height="32" HorizontalAlignment="Left" Text="{Binding Path=ContactNumber}" Margin="580,85,0,0" Name="txtContactNumber" VerticalAlignment="Top" Width="194" FontSize="16" />
    <TextBlock Height="34" HorizontalAlignment="Left" Margin="29,12,0,0" Name="txtbTitle" Text="Generate Token" VerticalAlignment="Top" FontSize="22" Foreground="#FF1313D8" Width="165" />
    <Button Content="Clear All" FontSize="20" Height="34" HorizontalAlignment="Left" Margin="418,328,0,0" Name="btnClearAll" VerticalAlignment="Top" Width="133" />
    <TextBox Height="108" HorizontalAlignment="Left" Margin="580,166,0,0" Text="{Binding Path=Address}" Name="txtAddress" VerticalAlignment="Top" Width="194" />
  </Grid>
</Page>

TokensViewModel.cs

class TokensViewModel:INotifyPropertyChanged
{
    #region Private Declaration
    private readonly token tokObject;
    private readonly ObservableCollection<token> _token;
    private readonly TokenManager tokenManager;
    private readonly ICommand _SaveCommand;
    ModelDataContext dataContext = new ModelDataContext();
    #endregion
    #region Constructor
    public TokensViewModel()
    {
        tokObject = new token();
        tokenManager = new TokenManager();
        _token = new ObservableCollection<token>();
        _SaveCommand = new RelayCommand(save, CanAdd);
    }
    #endregion
    #region SaveCommand
    public bool CanAdd(object obj)
    {
        if (Name != string.Empty && Address != string.Empty && ContactNumber.ToString() != null && PanNumber != string.Empty && PlateNumber != string.Empty)
            return true;
        else
            return false;
    }
    public void save(object obj)
    {
        dataContext.tokens.InsertOnSubmit(new token
        {
            vcrNameOfCustomer = Name,
            address = Address,
            contact_no = ContactNumber,
            pan_no = PanNumber,
            plate_no = PlateNumber
        });
        dataContext.SubmitChanges();
    }
    #endregion
    #region Commands
    public ICommand SaveCommand { get { return _SaveCommand; } }
    #endregion
    #region Properties
    public int Id
    {
        get { return tokObject.token_id; }
        set
        {
            tokObject.token_id = value;
            onPropertyChanged("Id");
        }
    }
    public Int64 ContactNumber
    {
        get { return tokObject.contact_no; }
        set
        {
            tokObject.contact_no = value;
            onPropertyChanged("ContactNumber");
        }
    }
    public string Address
    {
        get { return tokObject.address; }
        set
        {
            tokObject.address = value;
            onPropertyChanged("Address");
        }
    }
    public string PanNumber
    {
        get { return tokObject.pan_no; }
        set
        {
            tokObject.pan_no = value;
            onPropertyChanged("PanNumber");
        }
    }
    public string PlateNumber
    {
        get { return tokObject.plate_no; }
        set
        {
            tokObject.plate_no = value;
            onPropertyChanged("PlateNumber");
        }
    }
    public string Name
    {
        get { return tokObject.vcrNameOfCustomer; }
        set
        {
            tokObject.vcrNameOfCustomer = value;
            onPropertyChanged("Name");
        }
    }
    public ObservableCollection<token> tokens { get { return _token; } }
    #endregion
    #region INotifyProperty Members
    public event PropertyChangedEventHandler PropertyChanged;
    public void onPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
             PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    #endregion
}

生成令牌.xaml.cs

public partial class GenerateToken : Page
{
    public GenerateToken()
    {
        InitializeComponent();
    }
}

先感谢您。

4

2 回答 2

7

You need to declare an instance of your TokensViewModel in the XAML:

<Page ...
    xmlns:ViewModels="clr-namespace:xyz.PresentationLayer.ViewModel">
  <Page.Resources>
    <ViewModels:TokensViewModel x:Key="ViewModel" />
  </Page.Resources>
  <Grid ... DataContext="{Binding Source={StaticResource ViewModel}}">

The XAML above creates an instance and adds it to the Page.Resources dictionary with a key of ViewModel.

Alternatively, you can set this in the code-behind if you name your Grid:

<Grid x:Name="LayoutRoot">

public GenerateToken()
{
    InitializeComponent();
    LayoutRoot.DataContext = new TokensViewModel();
} 

The downside of binding it in code-behind is that in many circumstances, you get Intellisense and designer support when you establish the DataContext in the XAML. The reason for this is that the type of the DataContext is declared in XAML at design time. In the code-behind approach, the type is not known until run-time.

The Grid.DataContext is then bound to this instance of your TokensViewModel. The rest of your {Binding} in the controls within Grid inherit the DataContext such that you can bind with:

<TextBlock Name="lblName"
           Text="{Binding Name}" />
于 2013-09-21T08:12:38.690 回答
1

You have not set the DataContext for your page.

trying doing

DataContext = new TokensViewModel() after InitializeComponents()

于 2013-09-21T08:12:52.440 回答