Привязка MVVM к InkCanvas
Вопрос
Кажется, я наткнулся на блокпост.Мы используем MVVM с Prism и имеем представление, для которого требуется Ink Canvas.Я создал StrokeCollection, который привязан из моей ViewModel к представлению.Я могу установить коллекцию из своей модели представления, но изменения не поступают в ViewModel, пока пользователь рисует.Есть ли способ заставить это работать?
Моя собственность в моей ViewModel выглядит следующим образом:
private StrokeCollection _strokes;
public StrokeCollection Signature
{
get
{
return _strokes;
}
set
{
_strokes = value;
OnPropertyChanged("Signature");
}
}
Вот моя строка привязки XAML:
<InkCanvas x:Name="MyCanvas" Strokes="{Binding Signature, Mode=TwoWay}" />
По какой-то причине InkCanvas никогда не уведомляет ViewModel о каких-либо изменениях.
Решение
Проблема вашего подхода в том, что вы предполагаете, что InkCanvas
создает StrokeCollection
.Это не так — он просто добавляет и удаляет из него элементы.И если коллекция недоступна (т.является null
), привязка завершится неудачно, и InkCanvas
не буду делать что-либо с этим.Так:
- Вам необходимо создать единый
StrokeCollection
- Вы должны предположить, что изменится содержимое коллекции, а не сама коллекция.
Пример кода:
public class ViewModel : INotifyPropertyChanged
{
private readonly StrokeCollection _strokes;
public ViewModel()
{
_strokes = new StrokeCollection();
(_strokes as INotifyCollectionChanged).CollectionChanged += delegate
{
//the strokes have changed
};
}
public event PropertyChangedEventHandler PropertyChanged;
public StrokeCollection Signature
{
get
{
return _strokes;
}
}
private void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
И XAML:
<InkCanvas Strokes="{Binding Signature}"/>
Другие советы
В классе StrokeCollection есть событие StrokesChanged, которое всегда запускается, когда вы рисуете что-то в представлении.Это событие содержит обновленную коллекцию штрихов.
КСАМЛ:
<Grid>
<InkCanvas Strokes="{Binding Signature}"/>
</Grid>
ВМ:
public class TestViewModel : INotifyPropertyChanged
{
public StrokeCollection Signature { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
public TestViewModel()
{
Signature = new StrokeCollection();
Signature.StrokesChanged += Signature_StrokesChanged;
}
void Signature_StrokesChanged(object sender, StrokeCollectionChangedEventArgs e)
{
//PUT A BREAKPOINT HERE AND CHECK
Signature = (System.Windows.Ink.StrokeCollection)sender;
}
}
Надеюсь, поможет!