c# - 绑定(bind)到 viewmodel 不工作 mvvm

标签 c# wpf xaml mvvm datacontext

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

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

BusinessLogicLayer\TokenManager.cs

Commom\RelayCommand.cs

PresentationLayer\ViewModel\TokensViewModel.cs

PresentationLayer\Views\GenerateToken.xaml (Page)

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

token 管理器.cs

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

生成 token .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
}

GenerateToken.xaml.cs

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

提前致谢。

最佳答案

您需要在 XAML 中声明您的 TokensViewModel 实例:

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

上面的 XAML 创建了一个实例,并将其添加到 Page.Resources 字典中,键为 ViewModel

或者,如果您命名您的 Grid,您可以在代码隐藏中设置它:

<Grid x:Name="LayoutRoot">

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

在代码隐藏中绑定(bind)它的缺点是,在许多情况下,当您在 XAML 中建立 DataContext 时,您会获得 Intellisense 和设计器支持。这样做的原因是 DataContext 的类型是在设计时在 XAML 中声明的。在代码隐藏方法中,直到运行时才知道类型。

Grid.DataContext 然后绑定(bind)到您的 TokensViewModel 实例。 Grid 中控件中的其余 {Binding} 继承 DataContext,以便您可以绑定(bind):

<TextBlock Name="lblName"
           Text="{Binding Name}" />

关于c# - 绑定(bind)到 viewmodel 不工作 mvvm,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18930271/

相关文章:

wpf - 通过键入在 Wpf 数据网格中查找记录

c# - 除了抛出错误之外,我能否在执行期间以任何其他方式停止程序?

c# - SimpleMembershipProvider - 密码加密

c# - 在没有命令的情况下调用 ViewModel 中的方法

c# - 在将对象作为有效负载的 View 模型之间使用Prism 6 Event Aggregator

xaml 根据另一种颜色定义颜色

c# - 使用异步方法的结果

c# - 如何从 Visual Studio 将可执行文件发布到我的 Azure Function?

c# - 如何检测键盘输入代码页

xaml - 使用关键字将 clr 命名空间映射到 xaml 命名空间