2014-10-16 101 views
0

我有这个非常小的测试应用程序,它探索WPF中的对象绑定。我对这个本地类的实例有约束力。 我正在探索绑定到xaml中的本地对象,在运行时设置数据上下文并在运行时修改资源实例。 我使用了窗口和应用资源,看看它们的影响,定义如下:WPF动态引用的应用程序资源在运行时不可更新

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" /> 

的我[App | Window] EmptyData有一个空信息成员,我试图在运行时修改它。我正在窗口加载:

(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" }; 

下面主窗口的代码。绿色标签是预期的行为。蓝色标签表示未修改的资源,但不希望被修改(静态+窗口)。红色标签是意外的行为。请参阅内嵌评论。

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> 

即使在调试器窗口中的一个注意到的资源被修改 enter image description here

,在运行时有一个为蓝色和红色的标签,没有内容。我认为有空属性的资源有问题,有点甚至myAppBogusData得到更新。

enter image description here

回答

1

MyData必须按顺序执行INotifyPropertyChangedInfo财产通过结合更新。

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

+0

作品一种享受,谢谢。我的想法是不重新分配,只需修改属性。 – 2014-10-17 09:41:27

相关问题