.net - WPF MVVM + UserControl 与后面的代码

标签 .net wpf mvvm user-controls

出于某种原因,我在 MVVM WPF 应用程序中通过我的 ViewModel 绑定(bind)自定义用户控件时遇到问题。基本控件是一个带有三个文本框的日期输入表单。我正在使用用户控件的代码隐藏来捕获 textchange 事件以及一些操作。出于某种原因,向属性添加绑定(bind)永远不会触发。

用户控件的 XAML:

<UserControl x:Class="MYLibray.DateBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="300" Width="800">
<StackPanel>

    <Border CornerRadius="10" Height="200" BorderBrush="Gray" Background="Gray">
    <StackPanel Orientation="Horizontal" OpacityMask="{x:Null}" HorizontalAlignment="Center">
    <TextBox Name="txtMonth" Height="100" Width="90" BorderThickness="0,0,0,5" Background="{x:Null}" Text="" FontSize="72" TextChanged="TextChanged">
        <TextBox.BorderBrush>
            <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                <GradientStop Color="#FF000000" Offset="0"/>
                <GradientStop Color="#FF000000" Offset="1"/>
            </LinearGradientBrush>
        </TextBox.BorderBrush>
    </TextBox>
            <TextBlock Text="/" FontSize="72" Height="100" Width="50" />
            <TextBox x:Name="txtDay" Height="100" Width="90" Background="{x:Null}" BorderThickness="0,0,0,5" VerticalAlignment="Stretch" FontSize="72" TextChanged="TextChanged">
                <TextBox.BorderBrush>
                    <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                        <GradientStop Color="#FF000000" Offset="0"/>
                        <GradientStop Color="#FF000000" Offset="1"/>
                    </LinearGradientBrush>
                </TextBox.BorderBrush>
            </TextBox>
            <TextBlock Text="/19" FontSize="72" Height="100" Width="Auto" />
            <TextBox x:Name="txtYear" Height="100" Width="90" Background="{x:Null}" BorderThickness="0,0,0,5"  FontSize="72" TextChanged="TextChanged">
                <TextBox.BorderBrush>
                    <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                        <GradientStop Color="#FF000000" Offset="0"/>
                        <GradientStop Color="#FF000000" Offset="1"/>
                    </LinearGradientBrush>
                </TextBox.BorderBrush>
            </TextBox>
    </StackPanel>
    </Border>

</StackPanel>

代码隐藏:
public partial class DateBox : UserControl

{
  private string _date = "";
  public static DependencyProperty TextProperty = DependencyProperty.RegisterAttached("DateText", typeof(string), typeof(DateBox), new PropertyMetadata(TextPropertyChanged));
  public static DependencyProperty EnabledProperty = DependencyProperty.RegisterAttached("Enabled", typeof(bool), typeof(DateBox), null);

  public DateBox()
  {                                 
     InitializeComponent();
     this.DataContext = this;
     txtMonth.Focus();
  }

  public bool Enabled
  {
     get
     {
        return (bool)GetValue(DateBox.EnabledProperty);
     }
     set
     {
        SetValue(DateBox.EnabledProperty, value);

        txtDay.IsEnabled = value;
        txtMonth.IsEnabled = value;
        txtYear.IsEnabled = value;
     }
  }

  public string DateText
  {
     get
     {
        return (string)this.GetValue(TextProperty);
     }
     set
     {
        this.SetValue(TextProperty, value);
     }
  }

  static void TextPropertyChanged(DependencyObject property,DependencyPropertyChangedEventArgs args)
  {
     ((DateBox)property).OnTextPropertyChanged((object)args.NewValue);
  }

  private void OnTextPropertyChanged(object newValue)
  {
     _date = newValue.ToString();
     this.UpdateLayout();
     DateTime d;
     if (DateTime.TryParse(_date, out d))
     {
        txtDay.Text = d.Day.ToString();
        txtMonth.Text = d.Month.ToString();
        txtYear.Text = (d.Year - 1900).ToString();
     }
     else
     {
        txtDay.Text = "";
        txtMonth.Text = "";
        txtYear.Text = "";
     }

     DateText = d.ToShortDateString();
  }

  bool AreAllValidNumericChars(string str)
  {
     bool ret = true;
     if (str == System.Globalization.NumberFormatInfo.CurrentInfo.PositiveSign)
     {
        return ret;
     }
     int l = str.Length;
     for (int i = 0; i < l; i++)
     {
        char ch = str[i];
        ret &= Char.IsDigit(ch);
     }

     return ret;
  }

  private void TextChanged(object sender, TextChangedEventArgs e)
  {

     TextBox txt = (TextBox)sender;

     switch (txt.Name)
     {
        case "txtMonth":
           if (txt.Text.Length == 1)
           {
              if (Convert.ToInt32(txt.Text) > 1)
              {
                 string value = txt.Text;
                 txt.Text = "0" + value;
                 txtDay.Focus();
              }
           }
           if (txt.Text.Length == 2)
           {
              txtDay.Focus();
           }
           break;
        case "txtDay":
           if (txt.Text.Length == 1)
           {
              if (Convert.ToInt32(txt.Text) > 3)
              {
                 string value = txt.Text;
                 txt.Text = "0" + value;
                 txtYear.Focus();
              }
           }
           if (txt.Text.Length == 2)
           {
              txtYear.Focus();
           }
           break;

        case "txtYear":
           if (txt.Text.Length == 2)
           {
              DateTime d;
              string datestring = txtMonth.Text + "/" + txtDay.Text + "/19" + txtYear.Text;
              if (DateTime.TryParse(datestring,out d))
              {
                 DateText = d.ToShortDateString();
              }
           }
           break;
        default:
           break;
     }
  }

}

当我像这样在 DataTemplate 中创建用户控件时:
<uc:DateBox DateText="{Binding BirthDate}" />

我的 ViewModel 中的 BirthDate 的获取和设置永远不会设置。 VM 上的 BirthDate 是一个字符串。

最佳答案

查看 DataContext控制和父级的。

要帮助调试绑定(bind),请查看 Bea Stollnitz's blog

基本上,添加这个 xmlns由您控制

xmlns:diagnostics="clr-namespace:System.Diagnostics;assembly=WindowsBase"

然后将此添加到您的Binding (s)
{Binding ....    , diagnostics:PresentationTraceSources.TraceLevel=High }

关于.net - WPF MVVM + UserControl 与后面的代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/752906/

相关文章:

c# - 具有异步服务初始化的竞争条件

.net - 安全地允许多个客户端共享单个资源

c# - MVVM 绑定(bind)未显示在 View 中

c# - 如何在类似于 phpMyAdmin 的 asp.net 中创建动态表/字段

c# - 无法绑定(bind)依赖属性

wpf - MVVM : Bind property in ViewModel to property in a different VM?

c# - "Attempted to read or write protected memory."将项目添加到 List<>

c# - WPF 将文本框绑定(bind)到 ViewModel

python - 将 C 对象 (CFFI) 传递给 .NET (Pythonnet)

c# - 如何将 VC++ 2015 可再发行组件与我的 ClickOnce (.NET) 应用程序捆绑在一起?