AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / user-19550736

Denis Ivanov's questions

Martin Hope
Denis Ivanov
Asked: 2024-12-28 22:53:15 +0800 CST

属性更改时 WPF 控件不会更新

  • 5

我正在为我的大学期末项目(论文)开发一个 WPF 应用程序。目标之一是能够动态更改 UI 的语言。我认为按照我尝试的方式做这件事并不是一个好主意,因为它需要大量代码,但为了学习,我会坚持下去。这个想法是将 XAML 中的文本属性绑定到 LanguageViewModel 中的属性,当用户从下拉菜单中更改当前语言时,UI 中的所有字符串都应更改为所选语言。使用下面的代码,OnPropertyChanged 方法被执行,但 UI 元素没有更新,经过大量调试后,我仍然不知道原因。

我目前正在尝试使用单个 TextBlock 控件。我已将其放在注释之间,以便于查找。

这是我的 MainWindow.xaml

<Window x:Class="AdjustrixWPF.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:AdjustrixWPF"
    xmlns:userControls="clr-namespace:AdjustrixWPF.View.UserControls"
    mc:Ignorable="d"
    Title="MainWindow" WindowState="Maximized" Height="650" Width="850" WindowStyle="None"
    MouseLeftButtonDown="Window_MouseLeftButtonDown"
    Background="{DynamicResource BackgroundBrush}">
<Grid Name="MainGrid"
      Margin="5">
    <Grid.RowDefinitions>
        <RowDefinition Height="40"/>
        <RowDefinition Height="25*"/>
        <RowDefinition Height="75*"/>
        <RowDefinition Height="25"/>
    </Grid.RowDefinitions>
    <TabControl Grid.Row="0" Width="{Binding ElementName=MainGrid, Path=ActualWidth}" 
                HorizontalAlignment="Left" Grid.RowSpan="2" Background="{DynamicResource BackgroundBrush}" Style="{StaticResource TabControlStyle}">
        <TabItem Background="{DynamicResource BackgroundBrush}" 
                 Style="{StaticResource TabItemStyle}">
            <TabItem.Header>
                <userControls:TabHeader DataContext="{Binding languageViewModel}"
                    Text="File" 
                                        IsMouseOver="{Binding IsMouseOver, RelativeSource={RelativeSource AncestorType=TabItem}}"
                                        IsSelected="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=TabItem}}"
                                        Style="{StaticResource TabHeaderStyle}"
                                        Height="20"/>
            </TabItem.Header>
            <StackPanel Orientation="Horizontal">
                <Border BorderBrush="{DynamicResource ForegroundBrush}"
                        BorderThickness="0 0 1 0"
                        Margin="5">
                    <Grid Height="{Binding ActualHeight, RelativeSource={RelativeSource AncestorType=StackPanel}}"
                          Width="300"
                          x:Name="TabPanelGrid">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="50*"/>
                            <ColumnDefinition Width="25*"/>
                        </Grid.ColumnDefinitions>
                        <Grid Height="{Binding ElementName=TabPanelGrid, Path=ActualHeight}">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="10*"/>
                                <RowDefinition Height="45*"/>
                                <RowDefinition Height="45*"/>
                            </Grid.RowDefinitions>
                            <!-- =========================================================== -->
                            <!-- This is the control I am currently experimenting with-->
                            <TextBlock x:Name="AppearanceBlock"
                                Style="{StaticResource TextBlockTabPanel}"
                                       Text="{Binding languageViewModel.Appearance, UpdateSourceTrigger=PropertyChanged}"
                                       Margin="0 0 0 3"/>
                            <!-- =========================================================== -->
                            <userControls:LabeledComboBox LabelText="Language"
                                                          ComboBoxItemsSource="{Binding languageViewModel.Languages}"
                                                          ComboBoxSelectedItem="{Binding languageViewModel.CurrentLanguage, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                                                          Grid.Row="1"
                                                          x:Name="LanguageBox"/>
                            <userControls:LabeledComboBox LabelText="Theme"
                                                          ComboBoxItemsSource="{Binding Path=themeViewModel.Themes, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                                                          ComboBoxSelectedItem="{Binding Path=themeViewModel.SelectedTheme, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                                                          Grid.Row="2"
                                                          x:Name="ThemeBox"/>
                        </Grid>
                    </Grid>
                </Border>
            </StackPanel>
        </TabItem>
        <TabItem Style="{StaticResource TabItemStyle}">
            <TabItem.Header>
                <userControls:TabHeader Text="Data"
                                        IsMouseOver="{Binding IsMouseOver, RelativeSource={RelativeSource AncestorType=TabItem}}"
                                        IsSelected="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=TabItem}}"
                                        Style="{StaticResource TabHeaderStyle}"
                                        Height="20"/>
            </TabItem.Header>
            <StackPanel>

            </StackPanel>
        </TabItem>
    </TabControl>
    <StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
        <Button Content="_" Style="{DynamicResource TitleBarButtonStyle}" Name="Minimize" Click="Minimize_Click"/>
        <Button Content="🗖" Style="{DynamicResource TitleBarButtonStyle}" Name="Restore" Click="Restore_Click"/>
        <Button Content="╳" Style="{DynamicResource TitleBarButtonStyle}" Name="Close" Click="Close_Click"/>
    </StackPanel>
</Grid>

这是设置数据上下文的代码:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        this.MaxHeight = SystemParameters.MaximizedPrimaryScreenHeight;
        MainWindowViewModel mainWindowViewModel = new();
        this.DataContext = mainWindowViewModel;
    }

这是 MainWindowViewModel:

public class MainWindowViewModel : ViewModelBase
{

    public ThemeViewModel themeViewModel { get; set; }

    public LanguageViewModel languageViewModel { get; set; }

    public MainWindowViewModel()
    {
        themeViewModel = new ThemeViewModel();
        languageViewModel = new LanguageViewModel();
    }
}

这是语言视图模型:

internal class StringEntry
{
    public string Bulgarian { get; set; }
    public string English { get; set; }
    public StringEntry(string bg, string en)
    {
        Bulgarian = bg;
        English = en;
    }

    public string GetString(Language currentLanguage)
    {
        if (currentLanguage == Language.English)
        {
            return English;
        }
        return Bulgarian;
    }
}

public class LanguageViewModel : ViewModelBase
{
    private StringEntry file = new("Файл", "File");
    private StringEntry data = new("Данни", "Data");
    private StringEntry appearance = new("Изглед", "Appearance");
    private Language currentLanguage;

    public LanguageViewModel()
    {
        File = file.GetString(currentLanguage);
        Data = data.GetString(currentLanguage);
        Appearance = appearance.GetString(currentLanguage);
        //todo: later load it from AppData/Local
        currentLanguage = Language.English;
    }

    public string CurrentLanguage
    {
        get
        {
            return currentLanguage.ToString();
        }
        set
        {
            currentLanguage = Language.English.ToString() == value ? Language.English : Language.Bulgarian;
            File = Language.English == App.Language ? file.English : file.Bulgarian;
            Data = data.GetString(currentLanguage);
            Appearance = appearance.GetString(currentLanguage);
            OnPropertyChanged();
            OnPropertyChanged(nameof(File));
        }
    }

    public string File
    {
        get { return file.GetString(currentLanguage); }
        set
        {
            _ = value;
            OnPropertyChanged();
        }
    }

    public string Data
    {
        get { return data.GetString(currentLanguage); }
        set
        {
            _ = value;
            OnPropertyChanged();
        }
    }

    public string Appearance
    {
        get { return appearance.GetString(currentLanguage); }
        set { _ = value; OnPropertyChanged(); }
    }
}

这是基础视图模型类:

public class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler? PropertyChanged;

    public void OnPropertyChanged([CallerMemberName] string member = null)
    {
        PropertyChanged?.Invoke(member, new PropertyChangedEventArgs(member));
    }
}

任何帮助都将不胜感激!

wpf
  • 1 个回答
  • 31 Views

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    重新格式化数字,在固定位置插入分隔符

    • 6 个回答
  • Marko Smith

    为什么 C++20 概念会导致循环约束错误,而老式的 SFINAE 不会?

    • 2 个回答
  • Marko Smith

    VScode 自动卸载扩展的问题(Material 主题)

    • 2 个回答
  • Marko Smith

    Vue 3:创建时出错“预期标识符但发现‘导入’”[重复]

    • 1 个回答
  • Marko Smith

    具有指定基础类型但没有枚举器的“枚举类”的用途是什么?

    • 1 个回答
  • Marko Smith

    如何修复未手动导入的模块的 MODULE_NOT_FOUND 错误?

    • 6 个回答
  • Marko Smith

    `(表达式,左值) = 右值` 在 C 或 C++ 中是有效的赋值吗?为什么有些编译器会接受/拒绝它?

    • 3 个回答
  • Marko Smith

    在 C++ 中,一个不执行任何操作的空程序需要 204KB 的堆,但在 C 中则不需要

    • 1 个回答
  • Marko Smith

    PowerBI 目前与 BigQuery 不兼容:Simba 驱动程序与 Windows 更新有关

    • 2 个回答
  • Marko Smith

    AdMob:MobileAds.initialize() - 对于某些设备,“java.lang.Integer 无法转换为 java.lang.String”

    • 1 个回答
  • Martin Hope
    Fantastic Mr Fox msvc std::vector 实现中仅不接受可复制类型 2025-04-23 06:40:49 +0800 CST
  • Martin Hope
    Howard Hinnant 使用 chrono 查找下一个工作日 2025-04-21 08:30:25 +0800 CST
  • Martin Hope
    Fedor 构造函数的成员初始化程序可以包含另一个成员的初始化吗? 2025-04-15 01:01:44 +0800 CST
  • Martin Hope
    Petr Filipský 为什么 C++20 概念会导致循环约束错误,而老式的 SFINAE 不会? 2025-03-23 21:39:40 +0800 CST
  • Martin Hope
    Catskul C++20 是否进行了更改,允许从已知绑定数组“type(&)[N]”转换为未知绑定数组“type(&)[]”? 2025-03-04 06:57:53 +0800 CST
  • Martin Hope
    Stefan Pochmann 为什么 {2,3,10} 和 {x,3,10} (x=2) 的顺序不同? 2025-01-13 23:24:07 +0800 CST
  • Martin Hope
    Chad Feller 在 5.2 版中,bash 条件语句中的 [[ .. ]] 中的分号现在是可选的吗? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench 为什么双破折号 (--) 会导致此 MariaDB 子句评估为 true? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng 为什么 `dict(id=1, **{'id': 2})` 有时会引发 `KeyError: 'id'` 而不是 TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob:MobileAds.initialize() - 对于某些设备,“java.lang.Integer 无法转换为 java.lang.String” 2024-03-20 03:12:31 +0800 CST

热门标签

python javascript c++ c# java typescript sql reactjs html

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve