gpt4 book ai didi

c# - 如何使用静态事件将信息从附加行为传递到 View 模型?

转载 作者:行者123 更新时间:2023-11-30 21:55:50 25 4
gpt4 key购买 nike

在我看来,我有一个文本框的附加属性。附加属性对文本框输入执行验证并执行其他杂务。附加的属性验证例程引发了一个由 View 模型监视的事件。

  1. 这是否通过让 View 模型获取无效的文本框来“违反”MVVM 推理?
  2. 当包含文本框的用户控件被删除时,GC 将如何处理来自附加属性的静态事件?
  3. 如果需要特定代码来避免内存泄漏,那是如何完成的?
  4. 有没有更好的方法来做到这一点?

抱歉,列表太长了,但 Google 没有解决这种情况。

感谢任何帮助。感谢您的考虑。

(VS2010.net 4.5)

TIA

View 模型

class CheckInViewModel : SimpleViewModelBase
{
public CheckInViewModel()
{
InValidTextBoxes = new List<TextBox>();

Stargate_V.Helpers.ColorMaskingTextBoxBehavior.Validated += (sender, e) =>
{
if (e.valid)
InValidTextBoxes.Remove(e.sender);
else
InValidTextBoxes.Add(e.sender);
};
}

List<TextBox> InValidTextBoxes;


}

XAML

 <TextBox 
h:ColorMaskingTextBoxBehavior.Mask="^[MmFf]$"
Text="{Binding Sex}"
Height="24" HorizontalAlignment="Right" Margin="0,55,665,0" VerticalAlignment ="Top" Width="36" />

附加属性

  public class ColorMaskingTextBoxBehavior : DependencyObject
{
// Entrance point from Xaml
public static readonly DependencyProperty MaskProperty = DependencyProperty.RegisterAttached("Mask",
typeof(string),
typeof(ColorMaskingTextBoxBehavior),
new FrameworkPropertyMetadata(OnMaskChanged));
...........................

// Callback from XAML initialization of the attached property.
private static void OnMaskChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
var textBox = dependencyObject as TextBox;
var mask = e.NewValue as string;
textBox.PreviewTextInput -= textBox_PreviewTextInput;
textBox.PreviewKeyDown -= textBox_PreviewKeyDown;
DataObject.RemovePastingHandler(textBox, Pasting);
DataObject.RemoveCopyingHandler(textBox, NoDragCopy);
CommandManager.RemovePreviewExecutedHandler(textBox, NoCutting);


if (mask == null)
{
textBox.ClearValue(MaskProperty);
textBox.ClearValue(MaskExpressionProperty);
}
else
{
textBox.SetValue(MaskProperty, mask);
SetMaskExpression(textBox, new Regex(mask, RegexOptions.Compiled | RegexOptions.IgnorePatternWhitespace));
textBox.PreviewTextInput += textBox_PreviewTextInput;
textBox.PreviewKeyDown += textBox_PreviewKeyDown;
DataObject.AddPastingHandler(textBox, Pasting);
DataObject.AddCopyingHandler(textBox, NoDragCopy);
CommandManager.AddPreviewExecutedHandler(textBox, NoCutting);
}
}



private static void textBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
var textBox = sender as TextBox;
var maskExpression = GetMaskExpression(textBox);

string passHex = (string)textBox.GetValue(PassColorProperty);
string failHex = (string)textBox.GetValue(FailColorProperty);
Color passColor = Extensions.ToColorFromHex(passHex);
Color failColor = Extensions.ToColorFromHex(failHex);

if (maskExpression == null)
{
return;
}

var proposedText = GetProposedText(textBox, e.Text);

if (!maskExpression.IsMatch(proposedText))
{
textBox.Background = new SolidColorBrush(failColor);

ValidationEventArgs args = new ValidationEventArgs();
args.sender = textBox;
args.valid = false;
OnValidation(args);
}
else
{
textBox.Background = new SolidColorBrush(passColor);

ValidationEventArgs args = new ValidationEventArgs();
args.sender = textBox;
args.valid = true;
OnValidation(args);
}
}

从上面的代码调用的事件

    public static event EventHandler<ValidationEventArgs> Validated;

static void OnValidation(ValidationEventArgs e)
{
EventHandler<ValidationEventArgs> handler = Validated;
if (handler != null)
{
handler(null, e);
}
}


public class ValidationEventArgs : EventArgs
{
public TextBox sender;
public bool valid;
}

最佳答案

是的,我认为这违反了 MVVM。您的 View 模型应该不知道任何 View 。经常问自己的问题是“我可以在不创建任何 View 的情况下运行我的应用程序吗?”。在这种情况下,您的 View 模型直接与文本框列表交互,因此该模式被打破。

这里有几种方法可以实现您的目标,最简单的可能是在您的 View 模型中创建一个处理程序,当您的 TextBox 文本更改时调用该处理程序:

public delegate void ValidationDelegate(bool isValid);

public class MyViewModel : ViewModelBase
{
public ValidationDelegate ValidationHandler { get { return (isValid) => OnValidate(isValid); } }

private void OnValidate(bool isValid)
{
// handle the validation event here
}
}

现在您所需要的只是一个带有附加属性的行为,您可以将其绑定(bind)到此处理程序:

public class ValidateBehavior : Behavior<TextBox>
{
public ValidationDelegate Validated
{
get { return (ValidationDelegate)GetValue(ValidatedProperty); }
set { SetValue(ValidatedProperty, value); }
}

public static readonly DependencyProperty ValidatedProperty =
DependencyProperty.Register("Validated", typeof(ValidationDelegate), typeof(ValidateBehavior), new PropertyMetadata(null));

protected override void OnAttached()
{
base.OnAttached();
this.AssociatedObject.TextChanged += ValidateText;
}

protected override void OnDetaching()
{
base.OnDetaching();
this.AssociatedObject.TextChanged -= ValidateText;
}

private void ValidateText(object sender, TextChangedEventArgs e)
{
if (this.Validated != null)
{
bool isValid = true; // do text validation here
this.Validated(isValid);
}
}
}

然后最后将行为添加到有问题的 TextBox 并绑定(bind)处理程序:

    <TextBox>
<i:Interaction.Behaviors>
<behaviors:ValidateBehavior Validated="{Binding ValidationHandler}"/>
</i:Interaction.Behaviors>
</TextBox>

编辑:如果您不想使用混合行为,那么您也可以使用附加行为来完成:

public static class ValidateBehavior
{
public static ValidationDelegate GetValidate(TextBox textbox)
{
return (ValidationDelegate)textbox.GetValue(ValidateProperty);
}

public static void SetValidate(TextBox textbox, ValidationDelegate value)
{
textbox.SetValue(ValidateProperty, value);
}

public static readonly DependencyProperty ValidateProperty =
DependencyProperty.RegisterAttached(
"Validate",
typeof(ValidationDelegate),
typeof(ValidateBehavior),
new UIPropertyMetadata(null, OnValidateChanged));

static void OnValidateChanged(DependencyObject depObj, DependencyPropertyChangedEventArgs e)
{
var textbox = depObj as TextBox;
if (textbox == null)
return;

if (e.OldValue is ValidationDelegate)
textbox.TextChanged -= OnTextChanged;

if (e.NewValue is ValidationDelegate)
textbox.TextChanged += OnTextChanged;
}

static void OnTextChanged(object sender, RoutedEventArgs e)
{
if (!Object.ReferenceEquals(sender, e.OriginalSource))
return;

var textbox = e.OriginalSource as TextBox;
if (textbox != null)
{
var validate = GetValidate(textbox);
if (validate != null)
{
bool isValid = true; // do text validation here
validate(isValid);
}
}
}
}

以及相应的 XAML:

<TextBox behaviors:ValidateBehavior.Validate="{Binding ValidationHandler}" />

关于c# - 如何使用静态事件将信息从附加行为传递到 View 模型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31897394/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com