2

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

我已经按照指示设置了所有内容:绑定ViewModelView;DataContext

我有一个名为的inkCanvas画布View

ViewModel获取更新的项目数据时,我需要引用inkCanvas来创建一个CanvasRender实例public CanvasRender(Canvas canvas, ProjectData pdata)

问题出在 MVVM 中,ViewModel对此一无所知View,那么我如何在其中引用控件(inkCanvasView

PS(已编辑):我所做的解决方法是:当我将项目数据传递给 时ViewModel,我还传递了inkCanvasfromView的代码隐藏。嗯,现在我的代码隐藏不干净。

4

3 回答 3

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}" />
于 2012-09-25T18:28:54.397 回答
0

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

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

所以一旦你的画布被加载,你应该在你的视图模型中保存一个对它的引用。

于 2012-09-26T05:58:44.183 回答
0

在 MVVM 模式中,您不会直接在 ViewModel 中引用控件。在 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>
于 2012-09-24T19:40:21.153 回答