WPF MVVM将控件绑定到在viewmodel中设置的变量

时间:2013-04-03 03:29:40

标签: wpf mvvm

我有一个控件,在我的例子中是SciChart:SciChartSurface DataSet绑定到ChartData,ChartData是我的viewModel中的一个对象。

在这个控件中,我需要将AxisTitle绑定到我的viemodel中的变量。我如何访问变量? 我已经尝试过AxisTitle =“{Binding CharName}”或=“{Binding Source = {x:Static ViewModels:ViewModelKeys.ChartViewModel},Path = ChartName}”但它无效。

<UserControl x:Class="UI.WPF.Views.ChartView"
         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:SciChart="http://schemas.abtsoftware.co.uk/scichart"
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300"
         xmlns:ViewModels="clr-namespace:UI.ViewModels;assembly=UI.ViewModels"
         xmlns:meffed="http:\\www.codeplex.com\MEFedMVVM"
         meffed:ViewModelLocator.ViewModel="{x:Static ViewModels:ViewModelKeys.ChartViewModel}">
<Grid>
    <SciChart:SciChartSurface x:Name="sciChartSurface" DataSet="{Binding ChartData}">
        <SciChart:SciChartSurface.RenderableSeries>
            <SciChart:FastLineRenderableSeries SeriesColor="Red"/>
        </SciChart:SciChartSurface.RenderableSeries>

        <!--  Declare Axes  -->
        <SciChart:SciChartSurface.YAxis >
            <SciChart:NumericAxis AxisTitle="{Binding ???}" AxisAlignment="Left">
                <SciChart:NumericAxis.GrowBy>
                    <SciChart:DoubleRange Min="0.1" Max="0.1"/>
                </SciChart:NumericAxis.GrowBy>
            </SciChart:NumericAxis>
        </SciChart:SciChartSurface.YAxis>
        <SciChart:SciChartSurface.XAxis>
            <SciChart:DateTimeAxis AxisTitle="Time"
                                   DrawMajorGridLines="True"
                                   DrawMinorGridLines="True" 
                                   TextFormatting="HH:mm MMM dd">
                <SciChart:DateTimeAxis.GrowBy>
                    <SciChart:DoubleRange Min="0.1" Max="0.1"/>
                </SciChart:DateTimeAxis.GrowBy>
            </SciChart:DateTimeAxis>
        </SciChart:SciChartSurface.XAxis>

        <!--  Declare ChartModifiers  -->
        <SciChart:SciChartSurface.ChartModifier>
            <SciChart:ModifierGroup>
                <SciChart:RolloverModifier x:Name="rolloverModifier"
                                           DrawVerticalLine="True"
                                           SourceMode="AllSeries" />
                <SciChart:SeriesSelectionModifier />
                <SciChart:RubberBandXyZoomModifier IsXAxisOnly="True" IsEnabled="True"/>
                <SciChart:ZoomExtentsModifier ExecuteOn="MouseDoubleClick" />
                <SciChart:ZoomPanModifier x:Name="panModifier" IsEnabled="False"/>
                <SciChart:XAxisDragModifier/>
                <SciChart:YAxisDragModifier/>
            </SciChart:ModifierGroup>
        </SciChart:SciChartSurface.ChartModifier>
    </SciChart:SciChartSurface>
  </Grid>

2 个答案:

答案 0 :(得分:1)

您无法将变量/字段绑定到View。您可以仅绑定属性,因为绑定系统使用反射并仅查找不属于DataContext中的字段的属性。为该变量创建属性并将该属性绑定到View。我希望这会给你一个想法。

答案 1 :(得分:1)

首先,清楚了解data binding。请查看以下文章。

Data Binding Overview

WPF/MVVM Quick Start Tutorial

在这里,我将向您展示一个简单的example如何使用数据绑定。

假设我们的视图如下图所示。

enter image description here

我为此视图命名的viewmodel为AddPersonViewModel。此视图模型由ViewModelBase类继承(其具有任何视图模型的公共属性和方法)并使用另一个名为RelayCommand的类

这是ViewModelBase

/// <summary>
/// Base for the View Models.
/// </summary>
public class ViewModelBase : INotifyPropertyChanged
{

    /// <summary>
    /// Occurs when a property value changes.
    /// </summary>
    public event PropertyChangedEventHandler PropertyChanged;

    /// <summary>
    /// Notifies the property changed.
    /// </summary>
    /// <param name="propertyName">Name of the property.</param>
    protected void NotifyPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));  
        }
    }
}

这是RelayCommand

/// <summary>
/// Relay Command
/// </summary>
public class RelayCommand : ICommand
{
    /// <summary>
    /// Initializes a new instance of the <see cref="RelayCommand"/> class.
    /// </summary>
    /// <param name="execute">The execute.</param>
    public RelayCommand(Action<object> execute)
        : this(execute, null)
    {
    }

    /// <summary>
    /// Initializes a new instance of the <see cref="RelayCommand"/> class.
    /// </summary>
    /// <param name="execute">The execute.</param>
    /// <param name="canExecute">The can execute.</param>
    public RelayCommand(Action<object> execute, Predicate<object> canExecute)
    {
        if (execute == null)
            throw new ArgumentNullException("execute");
        _execute = execute;
        _canExecute = canExecute;
    }

    /// <summary>
    /// Defines the method that determines whether the command can execute in its current state.
    /// </summary>
    /// <param name="parameter">Data used by the command.  If the command does not require data to be passed, this object can be set to null.</param>
    /// <returns>
    /// true if this command can be executed; otherwise, false.
    /// </returns>
    public bool CanExecute(object parameter)
    {
        return _canExecute == null ? true : _canExecute(parameter);
    }

    /// <summary>
    /// Occurs when changes occur that affect whether or not the command should execute.
    /// </summary>
    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    /// <summary>
    /// Defines the method to be called when the command is invoked.
    /// </summary>
    /// <param name="parameter">Data used by the command.  If the command does not require data to be passed, this object can be set to null.</param>
    public void Execute(object parameter)
    {
        _execute(parameter);
    }

    /// <summary>
    /// Action
    /// </summary>
    private readonly Action<object> _execute;


    /// <summary>
    /// Predicate
    /// </summary>
    private readonly Predicate<object> _canExecute;
}

行。这是我的view model

public class AddPersonViewModel : ViewModelBase
{
    #region Declarations

    private string name;
    private int age;

    private ICommand addPersonCommand;

    #endregion

    #region Properties

    /// <summary>
    /// Gets or sets the name.
    /// </summary>
    /// <value>The name.</value>
    public string Name
    {
        get
        {
            return name;
        }
        set
        {
            name = value;
            NotifyPropertyChanged("Name");
        }
    }

    /// <summary>
    /// Gets or sets the age.
    /// </summary>
    /// <value>The age.</value>
    public int Age
    {
        get
        {
            return age;
        }
        set
        {
            age = value;
            NotifyPropertyChanged("Age");
        }
    }

    #endregion

    #region Commands


    /// <summary>
    /// Gets the add person command.
    /// </summary>
    /// <value>The add person command.</value>
    public ICommand AddPersonCommand
    {
        get
        {
            if (addPersonCommand == null)
            {
                addPersonCommand = new RelayCommand(param => this.AddPerson(),
                    null);
            }
            return addPersonCommand;
        }
    }

    #endregion

    #region Private Methods

    private void AddPerson()
    {
        // TODO: the logic to add a person
    }

    #endregion
}

最后这是我的view

<Page x:Class="PivotTest.AddPerson"
      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:viewmodel="clr-namespace:PivotTest.ViewModels"
      mc:Ignorable="d" 
      d:DesignHeight="300" d:DesignWidth="300"
    Title="AddPerson">

    <Grid>

        <Grid.DataContext>
            <viewmodel:AddPersonViewModel />
        </Grid.DataContext>

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="100" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="30" />
            <RowDefinition Height="30" />
            <RowDefinition Height="30" />
            <RowDefinition Height="30" />
        </Grid.RowDefinitions>

        <Label Grid.Column="0" Grid.Row="0" Content="Add Person" FontWeight="Bold" FontSize="16" /> 

        <Label Grid.Column="0" Grid.Row="1" Content="name" />
        <TextBox Grid.Column="1" Grid.Row="1"  Text="{Binding Name}" 
                 Margin="5,5,50,5"/>

        <Label Grid.Column="0" Grid.Row="2" Content="Age" />
        <TextBox Grid.Column="1" Grid.Row="2"  Text="{Binding Age}" 
                 Margin="5,5,50,5"/>

        <Button Grid.Column="1" Grid.Row="3" Content="Add" Command="{Binding AddPersonCommand}" 
                Margin="5, 5, 130, 5"/>
    </Grid>
</Page>

我认为这个简单的例子可能会对你有帮助。