【问题标题】:WPF dynamically referenced application resources not updateable at runtimeWPF 动态引用的应用程序资源在运行时不可更新
【发布时间】:2014-12-12 07:52:08
【问题描述】:

我有一个非常小的测试应用程序,用于探索 WPF 中的对象绑定。我绑定到这个class MyData { public string Info { get; set; } } 本地类的实例。 我正在探索绑定到 xaml 中的本地对象,在运行时设置数据上下文并在运行时修改资源实例。 我同时使用窗口和应用程序资源来查看它们的影响,定义如下:

App.xaml 资源

<local:MyData x:Key="myAppData" Info="App resource information" />
<local:MyData x:Key="myAppEmptyData" />
<local:MyData x:Key="myAppBogusData" Info="-" />

Window.xaml 资源

<local:MyData x:Key="myWindowData" Info="Window resource information" />
<local:MyData x:Key="myWindowEmptyData" />

my[App|Window]EmptyData 有一个 null Info 成员,我正在尝试在运行时对其进行修改。我在窗口加载时这样做:

(this.Resources["myWindowEmptyData"] as MyData).Info = "window resource info set on runtime";
(Application.Current.Resources["myAppEmptyData"] as MyData).Info = "app resource info set on runtime";
(Application.Current.Resources["myAppBogusData"] as MyData).Info = "app resource info set on runtime";
this.lblDataContextSetAtRuntime.DataContext = new MyData() { Info = "data context set at runtime" };

下面的主窗口代码。绿色标签是预期行为。蓝色标签代表人们期望不会被修改的未修改资源(静态 + 窗口)。红色标签是意外行为。也可以查看内联 cmets。

MainWindow.xaml

    <Grid VerticalAlignment="Stretch" HorizontalAlignment="Stretch" 
        DataContext="{StaticResource myWindowData}">
    <Grid.RowDefinitions>
      <RowDefinition Height="1*" /><RowDefinition Height="1*" /><RowDefinition Height="1*" /><RowDefinition Height="1*" /><RowDefinition Height="1*" /><RowDefinition Height="1*" /><RowDefinition Height="1*" /><RowDefinition Height="1*" />
    </Grid.RowDefinitions>   
    <!--this uses data context from the grid-->
    <Label Content="{Binding Path=Info}" Background="Green" Grid.Row="0" />
    <!--normal to not be updateable since window resources-->
    <Label DataContext="{StaticResource myWindowEmptyData}" Content="{Binding Path=Info}" Background="CadetBlue" Grid.Row="1" x:Name="lblStaticWindowResource" />
    <Label DataContext="{DynamicResource myWindowEmptyData}" Content="{Binding Path=Info}" Background="CadetBlue" Grid.Row="2" x:Name="lblDynamicWindowResource" />
    <!--data context set at runtime-->
    <Label Content="{Binding Path=Info}" Grid.Row="3" Background="Green" x:Name="lblDataContextSetAtRuntime" />
    <!--uses data context from app-->
    <Label DataContext="{StaticResource myAppData}" Content="{Binding Path=Info}" Background="Green" Grid.Row="4" x:Name="lblAppData" />
    <!--static app resource not modifiable-->
    <Label DataContext="{StaticResource myAppEmptyData}" Content="{Binding Path=Info}" Background="CadetBlue" Grid.Row="5" x:Name="lblStaticAppResource"/>
    <!--DYNAMIC APP RESOURCE SHOULD GET MODIFIED-->
    <Label DataContext="{DynamicResource myAppEmptyData}" Content="{Binding Path=Info}" Background="Red" Grid.Row="6" x:Name="lblDynamicEmptyAppResource" />
    <Label DataContext="{DynamicResource myAppBogusData}" Content="{Binding Path=Info}" Background="Red" Grid.Row="7" x:Name="lblDynamicBogusAppResource" />
  </Grid>

即使在调试器窗口中注意到资源已被修改

,在运行时没有蓝色和红色标签的内容。我认为具有 null 属性的资源存在问题,甚至 myAppBogusData 都没有更新。

【问题讨论】:

    标签: c# .net wpf xaml binding


    【解决方案1】:

    MyData 必须实现 INotifyPropertyChanged 才能通过绑定更新 Info 属性。

    class MyData : INotifyPropertyChanged
    {
        private string info;
        public string Info
        {
            get { return info; }
            set
            {
                if (info != value)
                {
                    info = value;
                    RaisePropertyChanged("Info");
                }
            }
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
    
        private void RaisePropertyChanged(string propertyName)
        {
            var handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
    

    除此之外,您不必使用DynamicResource - StaticResource 就足够了。如果您需要完全更改 MyData 实例,则只需要使用 DynamicResource。例如:

    Application.Current.Resources["myAppBogusData"] = new MyData() { Info = "New data" };
    

    如果您只是更改给定实例的属性,则可以使用StaticResource

    【讨论】:

    • 工作愉快,谢谢。我的想法不是重新分配,而是简单地修改属性。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多