【问题标题】:WPF Slider control (NullReferenceException)WPF 滑块控件 (NullReferenceException)
【发布时间】:2011-09-30 13:31:12
【问题描述】:

我正在尝试在 TextBlock 中显示滑块控件的值。但是,当我尝试加载对话框时,我不断收到 NullRerferenceException。

public partial class GeneralSettingsDialog : Window
{

    public GeneralSettingsDialog()
    {  
        InitializeComponent();
    }

    private void DistSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
    {
        DistTextBlock.Text = DistSlider.Value.ToString();
    }
}

XAML:

        <TabItem Header="Miscellaneous" Name="tabItem1" Background="#FFF0F0F0">
            <Grid Height="230" Background="#FFF0F0F0">
                <TextBlock Height="23" HorizontalAlignment="Left" Margin="13,13,0,0" Name="textBlock1" Text="Spacing" VerticalAlignment="Top" />
                <Slider Height="23" HorizontalAlignment="Left" IsSnapToTickEnabled="True" TickPlacement="BottomRight" Margin="13,35,0,0" Name="DistSlider" VerticalAlignment="Top" Width="100" Interval="1" Maximum="50" Minimum="1" ValueChanged="DistSlider_ValueChanged" />
                <TextBlock Height="23" HorizontalAlignment="Left" Margin="111,35,0,0" Name="DistTextBlock" Text="TextBlock" VerticalAlignment="Top" />

            </Grid>
        </TabItem>

【问题讨论】:

  • 尝试调试并检查对象 DistSlider.Value 是否为空。
  • 看来问题出在文本块上,因为该值在消息框中显示正常。
  • 请出示您的 XAML,这里没有水晶球。 :)
  • 在命名元素时尝试 x:Name 而不是 Name。
  • @dowhilefor,刚刚尝试过,但仍然遇到同样的异常。

标签: c# wpf


【解决方案1】:

不完全确定为什么你的方式不起作用,我猜当第一个值更改事件被抛出时,控件没有完全初始化。但是您可以直接在 xaml 中这样做,无需任何代码:

在TextBlock中直接绑定滑块的当前值并移除值改变事件处理程序:

 Text="{Binding ElementName=DistSlider, Path=Value}"

PS:

当您在 InitializeComponent() 之后的代码隐藏中附加到滑块的值更改事件时,您的方法也应该可以正常工作:

public MainWindow()
{
  InitializeComponent();
  DistSlider.ValueChanged +=new RoutedPropertyChangedEventHandler<double>(DistSlider_ValueChanged);
}

private void DistSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
    DistTextBlock.Text = DistSlider.Value.ToString();
}

【讨论】:

    【解决方案2】:

    在您的 XAML 中,您在 DistSlider 之后定义了 TextBlockDistTextBlock。第一次加载 XAML 时,它将触发 ValueChanged 处理程序,并且 DistTextBlock 将为空。您可以通过以下几种方式来防止这种情况:

    // 1. Naive, but least changes to your code
    if (DistTextBlock != null)
    {
        DistTextBlock.Text = DistSlider.Value.ToString();
    }
    

    @SvenG's excellent suggestion,它将逻辑移动到XAML(不需要ValueChanged 处理程序):

    <TextBlock Text="{Binding Value, ElementName=DistSlider}" ... />
    

    最后,您可以使用ViewModel(或任何data context supporting INotifyPropertyChanged)来处理值的传入和传出。

    使用绑定的重要部分是它允许您将任何 string formatting right alongside its usage 放入 XAML(例如,如果此滑块用于货币金额):

    <TextBlock Text="{Binding Value, ElementName=DistSlider, StringFormat={}{0:C}}"
    

    使用绑定的最后一个好处是在.Net Framework 4.5, which allows you to specify a time delay prior to the binding updating its source 中出现。如果绑定用于昂贵的操作,这将使您的 GUI 看起来更具反应性。

    <Slider Value="{Binding DollarAmount, Delay=50}" ... />
    <TextBlock Text="{Binding DollarAmount, StringFormat={}{0:C}}" ... />
    

    【讨论】:

    • 感谢您的解释!这真的很有帮助。
    • 感谢您的客气话。 Delay Binding 属性听起来真的很有帮助,肯定会在 4.5 中尝试一下 .. 感谢您提及!
    • @SvenG:不客气,我希望他会选择你的,因为这是第一个正确的;使用事件处理程序!我建议阅读.Net Framework 4.5 WPF changelog 以获得更多期待。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-31
    • 2011-12-10
    • 2018-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多