Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/271.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.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# 如何在使用异步绑定时避免闪烁_C#_Wpf_Asynchronous_Data Binding - Fatal编程技术网

C# 如何在使用异步绑定时避免闪烁

C# 如何在使用异步绑定时避免闪烁,c#,wpf,asynchronous,data-binding,C#,Wpf,Asynchronous,Data Binding,我已经创建了一个例子来说明我的问题 视图模型: public class VM : INotifyPropertyChanged { private double _value = 1; public double Value { get { return _value; } set { _value = value; OnPropertyChanged();

我已经创建了一个例子来说明我的问题

视图模型:

public class VM : INotifyPropertyChanged
{
    private double _value = 1;
    public double Value
    {
        get { return _value; }
        set
        {
            _value = value; 
            OnPropertyChanged();
        }
    }

    public VM()
    {
        var timer = new DispatcherTimer();
        timer.Interval = TimeSpan.FromTicks(1);
        timer.Tick += (s, e) => { Value += 1; };
        timer.Start();
    }

    // OnPropertyChanged stuff ... 
    }
}
视图:


运行我的应用程序时,文本框中的文本会闪烁。在更新过程中,将显示Fallback值,这对我来说毫无意义


是否有人知道更新过程中显示Fallback值的目的或好处?在异步更新过程中有没有显示旧值的方法?

有时绑定会失败,失败是很重要的考虑。如果发生错误,回退值选项会向用户显示一条消息,而不是什么都没有发生。如果希望fallbackvalue显示包含的前一个值,我可以考虑几种尝试方法:可能将该值保存在引用字符串中和/或另一个控件中,然后绑定到该控件


但是,如果您根本不想显示fallbackvalue,则需要进行代码检查,以查看绑定如何失败/或速度慢,并将其包含在代码隐藏中,这在我看来是正常的,因为您在绑定中使用了
IsAsync=True
。发件人:

在等待值到达时,绑定报告FallbackValue(如果有)

当引发
PropertyChanged
事件时,WPF启动更新绑定目标的过程。通常这将同步发生,立即调用属性getter来更新值

但是您使用的是
IsAysnc=True
,因此WPF将使用回退值填充目标,并启动异步请求以稍后检索实际属性值。在该请求完成之前,将显示回退值

是否有人知道更新过程中显示Fallback值的目的或好处

根据文档,IsAsync=True设置背后的意图是当属性getter是或可能是慢时使用它。您的代码告诉WPF属性值已更改,因此它知道旧值不再有效。您的代码还告诉(通过XAML中的
IsAsync
)属性getter可能需要一些时间来提供新值,因此它会将检索该值推迟到以后

同时,WPF应该显示什么?这就是回退值的作用

有没有办法在异步更新过程中显示旧值


如果您不希望在WPF中使用为该特性设计的行为,那么您应该自己异步检索新数据,并在有新数据时通过setter更新该属性。无论如何,属性获取程序速度慢不是一个好主意,因此无论如何这都是一个更好的设计。

我找到了一种方法,通过从textbox继承并重写其textproperty元数据来避免闪烁

自定义TextBoxControl

public class CustomTextBox : TextBox
{
    static CustomTextBox()
    {
        TextProperty.OverrideMetadata(typeof(CustomTextBox), new FrameworkPropertyMetadata(null, null, CoerceChanged));
    }

    private static object CoerceChanged(DependencyObject d, object basevalue)
    {
        var tb = d as TextBox;
        if (basevalue == null)
        {
            return tb.Text;
        }
        return basevalue;
    }
}
查看

<Window.DataContext>
    <namespace:VM/>
</Window.DataContext>
<Grid>
    <namespace:CustomTextBox Text="{Binding Value, IsAsync=True}"/>
</Grid>

让文本绑定不带回退值非常重要。因此,在更新过程中,文本被设置为textproperty defalut值-因此在本例中设置为null


强制更改处理程序检查新值是否为null。如果是这样,他将返回旧值,以便在更新过程中仍显示旧值

我也有同样的问题,但有一个图像源。我已删除绑定上的
IsAsync
,并使我的getter异步:

// This field hold a copy of the thumbnail.
BitmapImage thumbnail;

// Boolean to avoid loading the image multiple times.
bool loadThumbnailInProgress;

// I'm using object as the type of the property in order to be able to return
// UnsetValue.
public object Thumbnail
{
  get {
    if (thumbnail != null) return thumbnail;
 
    if (!loadThumbnailInProgress) {
      // Using BeginInvoke() allow to load the image asynchronously.
      dispatcher.BeginInvoke(new Action(() => {
        thumbnail = LoadThumbnail();
        RaisePropertyChanged(nameof(Thumbnail));
      }));
      loadThumbnailInProgress = true;
    }
    // Returning UnsetValue tells WPF to use the fallback value.
    return DependencyProperty.UnsetValue;
  }
}

他的装订没有坏。它只是简单地显示回退值,直到属性getter返回。@Peter,这正是我了解回退值是什么的方式,但我编辑了我的答案以包含slowresponse@ManDani,我会选择Peters的解决方案,但如果你想坚持你的方式和实验,尝试将回退值绑定到正在保存前一个值的字符串的隐藏控件displayed@JohnChris-您不能为FallbackValue设置绑定,因为它不是DependencyProperty。@ManDani,是的,刚才看到了,我同意。虽然在我的情况下,我没有一个缓慢的获得者。正如您所看到的,显示的值变化非常快。在我的实际应用程序中,a有几个文本框,因此视图需要很多时间。通过设置IsAsnyc=True,我试图避免冻结视图。因此,在我的情况下,显示后备值是没有意义的——它只会导致闪烁。“在我的情况下,我没有一个缓慢的获取者”——那么您使用
IsAsync=True
的动机是什么?发生了什么“冻结视图”及其原因?WPF可以轻松显示任意数量的文本框和其他控件,而不会出现明显的延迟;当你有足够的屏幕上的控件来放慢速度时,你有太多的控件让用户无论如何都无法理解。在我看来,您真正的问题不应该是关于
IsAsync
(您可能不应该使用它),而应该是关于为您的真实场景改善用户体验。这是一个有趣的解决方案。。虽然我不认为说你在这里压倒一切是准确的。。这更像是向处理程序注册派生类型(配置概念)。。您可能可以为其添加解析器模式。如果在调用
TextProperty.OverrideMetadata
时调用了
typeof(TextBox)
,它还会调用处理程序并提供相同的结果吗?。。如果您同时指定了
typeof(CustomTextBox)
typeof(TextBox)
处理程序是否触发两次?@BrettCaswell,则无法使用
typeof(TextBox)
-您将得到一个异常。因为已经为textbox textproperty注册了元数据。
// This field hold a copy of the thumbnail.
BitmapImage thumbnail;

// Boolean to avoid loading the image multiple times.
bool loadThumbnailInProgress;

// I'm using object as the type of the property in order to be able to return
// UnsetValue.
public object Thumbnail
{
  get {
    if (thumbnail != null) return thumbnail;
 
    if (!loadThumbnailInProgress) {
      // Using BeginInvoke() allow to load the image asynchronously.
      dispatcher.BeginInvoke(new Action(() => {
        thumbnail = LoadThumbnail();
        RaisePropertyChanged(nameof(Thumbnail));
      }));
      loadThumbnailInProgress = true;
    }
    // Returning UnsetValue tells WPF to use the fallback value.
    return DependencyProperty.UnsetValue;
  }
}