【问题标题】:Binding TextBlock to static variable将 TextBlock 绑定到静态变量
【发布时间】:2020-05-21 10:03:34
【问题描述】:

我正在尝试将TextBlock 绑定到静态变量。我已经阅读了一些指南和主题,这就是我想出的,但到目前为止还没有结果。

XAML:

xmlns:SQLLog="clr-namespace:DBM.SQLServerLogHandler" //SQLServerLogHandler - folder with LogDisplay class
xmlns:Converters="clr-namespace:DBM.Converters"
...
<Window.Resources>
        <Converters:StringListToStringConverter x:Key="ListToString"/>
</Window.Resources>
...
<TextBlock Grid.Row="1" Text="{Binding Source={x:Static SQLLog:LogDisplay.LogAdvanced}, Converter={StaticResource ListToString}}" FontSize="12"/>

静态类:

public static class LogDisplay
    {
        private static List<string> _logAdvanced;
        public static List<string> LogAdvanced 
        { 
            get 
            { 
                return _logAdvanced; 
            }
            set 
            {
                if(value != _logAdvanced)
                {
                    _logAdvanced = value;
                    if (StaticPropertyChanged != null)
                        StaticPropertyChanged(null, EventArgs.Empty);
                } 
            } 
        }

        public static event EventHandler StaticPropertyChanged;
    }

和转换器

class StringListToStringConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (targetType != typeof(string))
                throw new InvalidOperationException("The target must be a String");

            return String.Join(", ", ((List<string>)value).ToArray());
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

我在TextBlock 也有错误Object reference not set to an instance of an object,但程序编译正确。

结果:

无论我在 _logAdvanced 变量中更改什么,TextBlock 都保持空白。

预期结果:

TextBlock 显示变量。

【问题讨论】:

  • 更改属性也会更改字段。但是 TextBlock 仍然是空白的。

标签: c# wpf binding


【解决方案1】:

你有错误的StaticPropertyChanged 实现,可能是xaml 中的错误Binding

LogDisplay.cs

public static class LogDisplay
{
    private static List<string> _logAdvanced;
    public static List<string> LogAdvanced
    {
        get
        {
            return _logAdvanced;
        }
        set
        {
            if (value != _logAdvanced)
            {
                _logAdvanced = value;
                OnStaticPropertyChanged();
            }
        }
    }

    public static event PropertyChangedEventHandler StaticPropertyChanged;

    private static void OnStaticPropertyChanged([CallerMemberName]string propertyName = null)
    {
        StaticPropertyChanged?.Invoke(null, new PropertyChangedEventArgs(propertyName));
    }
}

查看

<TextBlock Grid.Row="1" Text="{Binding Path=(SQLLog:LogDisplay.LogAdvanced), Converter={StaticResource ListToString}}" FontSize="12"/>

这对我有用:当我在运行时将准备好的 List&lt;string&gt; 分配给 LogDisplay.LogAdvanced 时,TextBlock 会更新其布局,例如通过Button点击。

LogDisplay.LogAdvanced = new List<string>
{
    "dddd",
    "ffff"
};

还有对StringListToStringConverter的一些改动

return string.Join(", ", (List<string>)value);

顺便说一句,如果您在运行时动态修改 List 时需要更新 UI,我不建议使用此实现。现在 UI 将不会使用 LogAdvanced.Add(someString) 更新。

最好在没有 Converter 的情况下使用 string 属性并对其进行修改。 LogAdvancedText += someString + ", ";。或者使用模板化的ItemsControlBindingObservableCollection&lt;string&gt;

例如:

<ItemsControl ItemsSource="{Binding Path=(SQLLog:LogDisplay.LogAdvanced)}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <WrapPanel/>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding}"/>
                <TextBlock Text=", "/>
            </StackPanel>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>
public static class LogDisplay
{
    private static ObservableCollection<string> _logAdvanced;
    public static ObservableCollection<string> LogAdvanced
    {
        get
        {
            return _logAdvanced;
        }
        set
        {
            if (value != _logAdvanced)
            {
                _logAdvanced = value;
                OnStaticPropertyChanged();
            }
        }
    }

    public static event PropertyChangedEventHandler StaticPropertyChanged;

    private static void OnStaticPropertyChanged([CallerMemberName]string propertyName = null)
    {
        StaticPropertyChanged?.Invoke(null, new PropertyChangedEventArgs(propertyName));
    }
}

通过此实现,每个Add() 都会导致 UI 更新

LogDisplay.LogAdvanced.Add("Some text");

【讨论】:

  • 谢谢,只是检查一下。是的,它会动态变化。所以我想我会使用+=
  • @gaijn 我添加了一个ItemsControl 示例。仅供参考。
  • 好的,我做了一些测试,它完美无瑕。我已将列表更改为字符串并仅使用 +=,也摆脱了转换器。是的,所以,我发现的那个指南要么已经过时,要么就是垃圾。无论哪种方式,感谢您的帮助。标记为已解决。
猜你喜欢
  • 2011-02-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-10
  • 1970-01-01
  • 2014-04-05
相关资源
最近更新 更多