2

在弹出窗口上,我checkbox.IsChecked绑定了一个模型,但我想在显示窗口时从后面的 xaml 代码中检查它的状态。当在 windows 加载事件后面的代码中按名称检查复选框时,它尚未设置。我需要做一些特定于 UI 的事情,这就是为什么我需要知道窗口打开时复选框的值是什么,而我无法从 checkbox.IsChecked 绑定到的模型中执行此操作。

模型上的属性在弹出窗口打开之前很久就设置好了,所以这不是绑定不存在的问题。我认为一旦 Loaded 事件触发,窗口就会准备好使用绑定和所有内容,但情况似乎并非如此。

xml:

<RefinedRibbonControls:RefinedRibbonGroup Header="Show Graphs">
                    <StackPanel x:Name="panelVisibilities">
                        <CheckBox Content="Show/hide" x:Name="myCheckBox"                                 
                                  IsChecked="{Binding Path=Processor.Model.IsItemVisible}"
                                  Click="GraphVisibilityClickEvent"
                                  HorizontalAlignment="Left"/>
...etc

模型属性:

public bool IsItemVisible
        {
            get { return _isItemVisible ; }
            set
            {
                if (_isItemVisible != value)
                {
                    _isItemVisible = value;
                    _propertyChanger.FirePropertyChanged(this, m => m.IsItemVisible);
                }
            }
        }

Xaml 代码隐藏中的事件:

private void WindowLoadedEvent(object sender, RoutedEventArgs e)
        {
            if(myCheckBox.IsChecked.Value)
            {
                // Do UI Related Stuff
            }
         }

绑定工作正常,显示窗口时显示值,问题是我无法在窗口加载事件中获取绑定的值。

编辑:我找到了可能的解决方案,但我不确定它是否是最好的方法。我从后面的 xaml 代码的构造函数中调用了以下方法。

private void SetupInitialVisibility()
        {
            //Fire after everything is loaded.
            Dispatcher.BeginInvoke(DispatcherPriority.ContextIdle, new Action(() =>
            {
                IEnumerable<CheckBox> elements = this.panelVisibilities.Children.OfType<CheckBox>().ToList();
                foreach (CheckBox checkBox in elements)
                {
                    if (checkBox.IsChecked != null && checkBox.IsChecked.Value == false)
                    {
                        //Do work
                    }
                }


            }));
        }

发现于:https ://stackoverflow.com/a/1746975/1253746

4

2 回答 2

3

数据绑定不是同步完成的,而是延迟的。检查此 msdn 页面上的调度程序优先级。它以低于普通窗口消息的优先级完成,但在渲染之前完成。

您可以调用自己的方法,其优先级低于为数据绑定定义的优先级,在此方法中您应该能够安全地读取数据绑定值。

我仍然会觉得这很难看。我宁愿直接订阅PropertyChanged并检查此属性,或者更好的是,将您的“UI 相关代码”重写为数据绑定。

PS 如果您开始消费事件,请务必取消订阅,否则您可能会出现内存泄漏。

于 2013-03-05T22:06:28.953 回答
1

我认为 DataBinding 应该在 Loaded 事件之前。

何时以及如何设置 DataContext?你肯定 viewmodel 属性已经设置了吗?

以下工作,如果可能,请尝试将您的代码与此对齐。

xml:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication1"
        Title="MainWindow" Height="350" Width="525">

    <Window.DataContext>
        <local:ViewModel />
    </Window.DataContext>
    <Grid>
        <CheckBox x:Name="myCheckBox" IsChecked="{Binding IsItemVisible}" />
    </Grid>
</Window>

代码背后:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        this.Loaded += MainWindow_Loaded;
    }

    void MainWindow_Loaded(object sender, RoutedEventArgs e)
    {
        if (myCheckBox.IsChecked.Value)
        {
            //...
        }
    }
}

视图模型:

public class ViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private bool isItemVisible;
    public bool IsItemVisible { get { return isItemVisible; } set { isItemVisible = value; OnPropertyChanged("IsItemVisible"); } }


    public ViewModel()
    {
        this.IsItemVisible = true;
    }

    private void OnPropertyChanged(string propertyName)
    {
        if (this.PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

在此处输入图像描述

于 2013-03-05T22:17:22.087 回答