MVVM- Как я могу выбрать текст в текстовом поле?
-
25-09-2019 - |
Вопрос
Есть ли MVVM способ выбрать текст в текстовом поле? MVVM Framework, которые я использую, это MVVM Laurent MVVM Lightkit.
Решение
Всякий раз, когда я пытаюсь напрямую повлиять на вид в «чистом» приложении MVVM (без кода сзади), я буду использовать Прикрепленные свойства Чтобы инкапсулировать любой эффект, который я пытаюсь достичь. Я создам интерфейс, который определяет действия, которые я хочу использовать с использованием пользовательских событий. Затем я реализую этот интерфейс в каждом ViewModel, который будет «запущен» эти команды на вид. Наконец, я связываю мой ViewModel в прилагаемое свойство в определении моего представления. Следующий код показывает, как это для Selectall и TextBox. Этот код может быть легко расширен для выполнения практически любого действия на любом компоненте в виду.
Мое прилагаемое свойство и определение интерфейса:
using System.Windows;
using System.Windows.Controls;
using System;
using System.Collections.Generic;
namespace SelectAllSample
{
public static class TextBoxAttach
{
public static readonly DependencyProperty TextBoxControllerProperty = DependencyProperty.RegisterAttached(
"TextBoxController", typeof(ITextBoxController), typeof(TextBoxAttach),
new FrameworkPropertyMetadata(null, OnTextBoxControllerChanged));
public static void SetTextBoxController(UIElement element, ITextBoxController value)
{
element.SetValue(TextBoxControllerProperty, value);
}
public static ITextBoxController GetTextBoxController(UIElement element)
{
return (ITextBoxController)element.GetValue(TextBoxControllerProperty);
}
private static readonly Dictionary<ITextBoxController, TextBox> elements = new Dictionary<ITextBoxController, TextBox>();
private static void OnTextBoxControllerChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var element = d as TextBox;
if (element == null)
throw new ArgumentNullException("d");
var oldController = e.OldValue as ITextBoxController;
if (oldController != null)
{
elements.Remove(oldController);
oldController.SelectAll -= SelectAll;
}
var newController = e.NewValue as ITextBoxController;
if (newController != null)
{
elements.Add(newController, element);
newController.SelectAll += SelectAll;
}
}
private static void SelectAll(ITextBoxController sender)
{
TextBox element;
if (!elements.TryGetValue(sender, out element))
throw new ArgumentException("sender");
element.Focus();
element.SelectAll();
}
}
public interface ITextBoxController
{
event SelectAllEventHandler SelectAll;
}
public delegate void SelectAllEventHandler(ITextBoxController sender);
}
Мое определение моделя
public class MyViewModel : ITextBoxController
{
public MyViewModel()
{
Value = "My Text";
SelectAllCommand = new RelayCommand(p =>
{
if (SelectAll != null)
SelectAll(this);
});
}
public string Value { get; set; }
public RelayCommand SelectAllCommand { get; private set; }
public event SelectAllEventHandler SelectAll;
}
Мой вид определения:
<Window x:Class="SelectAllSample.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:loc="clr-namespace:SelectAllSample"
Title="Window1" Height="150" Width="150">
<x:Code><![CDATA[
public Window1()
{
InitializeComponent();
DataContext = new MyViewModel();
}
]]></x:Code>
<StackPanel>
<TextBox Text="{Binding Value}" loc:TextBoxAttach.TextBoxController="{Binding}" />
<Button Content="Select All" Command="{Binding SelectAllCommand}" />
</StackPanel>
</Window>
Примечание: Благодаря Джош Смиту для релайомманда (см. Код на рисунке 3 на эта страница). В этом примере используется в MyViewModel в этом примере (и почти все мой код MVVM).
Другие советы
Найти хорошее введение в прикрепленные свойства здесь:http://www.codeproject.com/kb/wpf/attachedbehaviors.aspx.