Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/backbone.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 跟踪UWP中的表单是否脏_C#_Uwp - Fatal编程技术网

C# 跟踪UWP中的表单是否脏

C# 跟踪UWP中的表单是否脏,c#,uwp,C#,Uwp,我试图跟踪UWP中表单的脏(修改)状态,该表单在视图和模型之间使用双向绑定 我目前跟踪各个已更改事件的方法(文本框的TextChange、组合框的SelectionChanged等)在页面加载数据时除外 似乎正在发生的事情是,在页面完全加载之后,仍然在对绑定进行评估,从而使表单认为它已被修改。通过逐步浏览我的代码,我在加载页面时构建了以下典型的时间线: 模型已初始化(脏=假) 将检索数据并将其放置在模型中 绑定触发,填充表单(dirty=true) 页面的已加载事件被命中,此时我设置dirty

我试图跟踪UWP中表单的脏(修改)状态,该表单在视图和模型之间使用双向绑定

我目前跟踪各个已更改事件的方法(文本框的TextChange、组合框的SelectionChanged等)在页面加载数据时除外

似乎正在发生的事情是,在页面完全加载之后,仍然在对绑定进行评估,从而使表单认为它已被修改。通过逐步浏览我的代码,我在加载页面时构建了以下典型的时间线:

  • 模型已初始化(脏=假)
  • 将检索数据并将其放置在模型中
  • 绑定触发,填充表单(dirty=true)
  • 页面的已加载事件被命中,此时我设置dirty=false
  • 继续设置绑定,从而将dirty重置为true
  • (我需要一些东西将dirty设置为false)
是否存在在第一次评估所有绑定后触发的事件,或者以某种方式跟踪是否已评估所有绑定

编辑:一些粗略的示例代码,以便更好地了解我是如何设置的

型号:

public class OrderModel : INotifyPropertyChanged
{ 
     private OrderCase order;
     public OrderCase Order
     {
        get
        {
            return order;
        }
        set
        {
            order = value;

            this.RaisePropertyChanged("Order");
        }
     }
    private bool dirty;
    public bool Dirty
    {
        get
        {
            return dirty;
        }
        set
        {
            dirty = value;
        }
    }
}
视图-代码隐藏

    OrderModel Model;
    int OrderId;
    protected async override void OnNavigatedTo(NavigationEventArgs e)
    {
       //Call a method in the View Model which calls a WCF service
       //to get the OrderCase object out of our database and into the
       //Order object in the model
       Model = new OrderModel();
       Model.Order = await WcfService.GetOrder(OrderId);
       //Once this returns all the bindings start evaluating
    }
    private void Page_Loaded(object sender, RoutedEventArgs e)
    {
       SetUndirty();
    }
    public override void TextBoxSetDirty(object sender, TextChangedEventArgs e)
    {
        //one of these exists for each type of control I use
        //this gets triggered when the text changes due to the model changing
        SetDirty();
    }
    public void SetDirty()
    {
        Model.Dirty = true;
    }
视图-XAML

<TextBox 
 Text = "{x:Bind Path=Order.CustomerName, mode=TwoWay}"
 TextChanged="TextBoxSetDirty"/>
最终的结果是,在用户对表单执行某种交互之前,不能将表单设置为Dirty


这在75%的时间内有效,并且不会产生误报(如果表单不干净,则表示表单脏了),但确实会产生一些误报,因为单击单选按钮、复选框或切换开关时,点击事件似乎不会触发。如果用户执行的唯一交互是在文本框中按一个键,那么它也会失败,因为在按下键之前会触发TextChanged事件,但是我们的用户只在文本框中输入一个字符的可能性微乎其微,因为他们的修改几乎没有,所以这一点不是主要问题。

您的ViewModel是如何安装的

对于您的班级:

public class OrderModel : INotifyPropertyChanged
{ 
     private OrderCase order;
     public OrderCase Order
     {
        get
        {
            return order;
        }
        set
        {
            if (value != order) { IsDirty = true; }
            order = value;

            this.RaisePropertyChanged("Order");
        }
     }
    private bool dirty;
    public bool Dirty
    {
        get
        {
            return dirty;
        }
        set
        {
            dirty = value;
        }
    }
}
这应该有效,还是无效

OrderModel Model;
int OrderId;
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
   //Call a method in the View Model which calls a WCF service
   //to get the OrderCase object out of our database and into the
   //Order object in the model
   var tempModel = new OrderModel();
   tempModel = await WcfService.GetOrder(OrderId);
   Model.Order = tempModel;
   //Setting the ViewModel's property only when getting order is completed
   //Once this returns all the bindings start evaluating
}
private void Page_Loaded(object sender, RoutedEventArgs e)
{
   SetUndirty();
}
public override void TextBoxSetDirty(object sender, TextChangedEventArgs e)
{
    //one of these exists for each type of control I use
    //this gets triggered when the text changes due to the model changing
    SetDirty();
}
public void SetDirty()
{
    Model.Dirty = true;
}

否则,您可以尝试在ViewModel中添加每个属性,而不是仅添加OrderCase的一个副本。。。只是一个想法

您不能在其他属性设置程序中设置IsDirty属性吗?只有当数据发生更改时,才会调用setter。问题是绑定到表单并存储在模型中的实际数据的类型来自WCF数据协定,因此,来自WCF的对象中属性的设置程序无法访问模型的IsDirty字段。您如何知道绑定的设置(最后一个要点)已完成?这个问题的答案基本上取决于绑定设置后触发的任何事件。如果没有事件,这将是一个猜谜游戏。您是否可以添加一个方法来设置私有属性而不是公共属性,从而不触发NotifyPropertyChangedEvent@Flater我的理解是,加载的事件应该是在用户拥有控制权之前触发的最后一个事件,但是,在加载事件之后,仍然会触发对_change事件的控制,这几乎就像竞争条件一样。如果设置了整个Order对象,这会起作用,但是OrderCase类型中有一组对象和属性,这些对象和属性绑定到视图。是顺序中的单个对象,如字符串CustomerName,在更改时需要将dirty属性设置为true。如何设置dirty属性?你能给我们看一个更完整的代码吗?谢谢这不起作用有两个原因:1。尽管OnNavigatedTo方法发生了更改,但竞争条件仍然存在。页面加载方法完成后,仍在评估绑定。2.在Order setter中设置Dirty不起作用,因为Order对象只是在最开始时设置的,当OrderCase中的属性被设置时,setter不会触发。如果您不能控制OrderModel,您可以修改ViewModel并公开OrderModel的每个属性,因此,您可以访问每个属性的设置程序。。。我知道这不是最好的解决办法
OrderModel Model;
int OrderId;
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
   //Call a method in the View Model which calls a WCF service
   //to get the OrderCase object out of our database and into the
   //Order object in the model
   var tempModel = new OrderModel();
   tempModel = await WcfService.GetOrder(OrderId);
   Model.Order = tempModel;
   //Setting the ViewModel's property only when getting order is completed
   //Once this returns all the bindings start evaluating
}
private void Page_Loaded(object sender, RoutedEventArgs e)
{
   SetUndirty();
}
public override void TextBoxSetDirty(object sender, TextChangedEventArgs e)
{
    //one of these exists for each type of control I use
    //this gets triggered when the text changes due to the model changing
    SetDirty();
}
public void SetDirty()
{
    Model.Dirty = true;
}