如何解决方法引用View的控件

时间:2012-09-24 19:27:07

标签: silverlight mvvm view viewmodel mvvm-light

我正在为我的Siverlight项目使用Galasoft的Light MVVM。

我按照说明设置了所有内容:ViewModel绑定到View的{​​{1}};

我在DataContext中有一个名为inkCanvas的画布。

View获取更新的项目数据时,我需要引用ViewModel来创建inkCanvas实例CanvasRender

问题出在MVVM中,public CanvasRender(Canvas canvas, ProjectData pdata)ViewModel一无所知,那么如何在View中引用控件(inkCanvas)?

P.S。 (已编辑):我所做的解决方法是:当我将项目数据传递给View时,我也会从ViewModel的代码隐藏中传递inkCanvas。嗯,现在我的代码隐藏不干净了。

3 个答案:

答案 0 :(得分:1)

根据上述评论,一种方法是扩展Canvas并在该类中保留对CanvasRender的引用。

public class MyCanvas : Canvas
{
    private CanvasRender _canvasRender;
    private ProjectData _data;

    public ProjectData Data
    {
        get { return _data; }       
        set
        {
            _data = value;
            _canvasRender = new CanvasRender(this, _data);
        }
    }

    public MyCanvas() : base()
    {
    }
}

您可能还想让ProjectData成为依赖属性,以便它可绑定。

这允许您维护MVVM模式,因为现在您可以使用XAML编写:

<local:MyCanvas ProjectData="{Binding ViewModel.ProjectData}" />

答案 1 :(得分:0)

在MVVM Pattern中,您不会直接在ViewModel中引用Control。在MVVM中,所有都是“绑定”。您的inkCanvas将绑定到ViewModel中的属性。

public class MyViewModel : INotifyPropertyChanged
{
    private readonly StrokeCollection _mystrokes;

    public MyViewModel ()
    {
        _mystrokes= new StrokeCollection();
        (_mystrokesas INotifyCollectionChanged).CollectionChanged += delegate
        {
            //the strokes have changed
        };
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public StrokeCollection MyStrokes
    {
        get
        {
            return _mystrokes;
        }
    }

    private void OnPropertyChanged(string propertyName)
    {
        var handler = PropertyChanged;

        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

和XAML:

<InkCanvas Strokes="{Binding MyStrokes}"/>

修改:

也许你的案例的解决方法是使用EventToCommand:这允许直接在XAML中将一个UI事件发送到ICommand(并使用Args将ref传递给inkCancas)

<i:Interaction.Triggers>
    <i:EventTrigger EventName="Loaded">
        <cmd:EventToCommand Command="{Binding Mode=OneWay, Path=LoadedCommand}"
                            PassEventArgsToCommand="True" />
    </i:EventTrigger>
</i:Interaction.Triggers>

答案 2 :(得分:0)

如果您要使用EventToCommand方法(您在另一个答案中尝试过),那么使用CommandParameter属性并将其绑定到Canvas,而不是使用PassEventArgsToCommand属性。

<i:Interaction.Triggers>
    <i:EventTrigger EventName="Loaded">
        <cmd:EventToCommand Command="{Binding Path=CanvasLoadedCommand}"
                            CommandParameter="{Binding ElementName=inkCanvas}" />
    </i:EventTrigger>
</i:Interaction.Triggers>

然后在你的ViewModel中:

public class ViewModel
{
    private Canvas m_canvas;

    public RelayCommand<Canvas> CanvasLoadedCommand { get; private set; }

    public ViewModel() 
    { 
        CanvasLoadedCommand = new RelayCommand<Canvas>(canvas =>  
        { 
            m_canvas = canvas;
        }); 
    }
}

因此,只要加载了画布,就应该在视图模型中保存对它的引用。