我正在为我的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
。嗯,现在我的代码隐藏不干净了。
答案 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;
});
}
}
因此,只要加载了画布,就应该在视图模型中保存对它的引用。