在窗口和应用程序级别引用的单个资源文件是否只有一个实例?

时间:2013-07-17 13:03:31

标签: wpf binding resourcedictionary

我有松散的MVVM形式,我有一个C#类,包含我的XAML绑定的资源数据。该文件在两个位置引用,MainWindow.xaml文件和App.xaml文件中的应用程序级别。当我在MainWindow代码隐藏中引用它时,似乎只有一个实例,我可以在窗口级别和应用程序级别中看到的那个实例中设置值。有人能确认或纠正这个假设吗? 请参阅下面的编辑

我有一个MainWindow和一个MainWindowResource.cs文件来支持MainWindow的绑定。资源文件看起来像这样(缩短):

public class MainWindowResource : INotifyPropertyChanged
{
    #region Data Members

    private Color _arrowBorderColor = Colors.Black;
    private Color _arrowColor = Colors.Black;
    private bool _viewFitYAxis = true;
    private string _viewFitYAxisTooltip = "";

    #endregion Data Members

    #region Properties

    public Color ArrowBorderColor
    {
        get { return _arrowBorderColor; }
        set { _arrowBorderColor = value; SetPropertyChanged("ArrowBorderColor"); }
    }

    public Color ArrowColor
    {
        get { return _arrowColor; }
        set { _arrowColor = value; SetPropertyChanged("ArrowColor"); }
    }

    public bool ViewFitYAxis
    {
        get { return _viewFitYAxis; }
        set { _viewFitYAxis = value; SetPropertyChanged("ViewFitYAxis"); }
    }

    public string ViewFitYAxisTooltip
    {
        get { return _viewFitYAxisTooltip; }
        set { _viewFitYAxisTooltip = value; SetPropertyChanged("ViewFitYAxisTooltip"); }
    }

    #endregion Properties

    #region INotifyPropertyChanged implementation

    public event PropertyChangedEventHandler PropertyChanged;
    private void SetPropertyChanged(string prop)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(prop));
        }
    }

    #endregion INotifyPropertyChanged implementation
}

我引用了MainWindow XAML中的MainWindowResouce文件:

<Window.Resources>
    <c:MainWindowResource x:Key="MainWindowResource"/>

我绑定到MainWindow XAML中MainWindowResource的属性:

<MenuItem x:Name="MenuFitYAxis"
    Header="Fit _Y Axis"
    IsCheckable="True"
    IsChecked="{Binding Source={StaticResource MainWindowResource}, Path=ViewFitYAxis}"
    ToolTip="{Binding Source={StaticResource MainWindowResource}, Path=ViewFitYAxisTooltip}"
    Click="MenuItem_Click_ViewFitYAxis"/>

我还有一个名为ArrowResources.xaml的资源字典,其中我定义了一些箭头路径。我还希望将一些值外部化到MainWindowResource文件中,使其看起来像这样(缩短):

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                xmlns:c="clr-namespace:UserInterface">
    <c:MainWindowResource x:Key="MainWindowResource"/>

    <Path x:Key="ArrowCounter"
        Stroke="{Binding Source={StaticResource MainWindowResource}, Path=ArrowBorderColor}"
        StrokeThickness="1"
        Data="M 8,26 L 14,20 L 10,20 A 10,10 0 1 1 30,20 L 34,20 A 14,14 0 1 0 6,20 L 2,20 Z">
        <Path.Fill>
            <RadialGradientBrush GradientOrigin="0.15,0.2" Center="0.3,0.4">
                <GradientStop Color="White"
                    Offset="0"/>
                <GradientStop Color="{Binding Source={StaticResource MainWindowResource}, Path=ArrowColor}"
                    Offset="1"/>
            </RadialGradientBrush>
        </Path.Fill>
    </Path>

</ResourceDictionary>

资源字典包含在我的App.xaml中,如下所示:

<Application x:Class="UserInterface.App"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         StartupUri="MainWindow.xaml">
    <Application.Resources>
        <ResourceDictionary Source="ArrowResources.xaml"/>
    </Application.Resources>
</Application>

在我的MainWindow的代码隐藏中,我获取了对MainWindowResource类的引用,如下所示(缩短):

public partial class MainWindow : Window
{
    private MainWindowResource _mainWindowResource = null;
    public MainWindow()
    {
        InitializeComponent();

        // get a reference to the binding sources so we can set the properties
        _mainWindowResource = (MainWindowResource)this.Resources["MainWindowResource"];
    }
}

当我得到这个引用时,似乎只有一个MainWindowResource类的实例,如果我在其中设置了值,那些更改将反映在应用程序级别的MainWindow.xaml和ArrowResources.xaml中。 / p>

任何人都可以证实这一点,或者纠正我的假设吗?

修改

我错了。 ArrowResources.xaml确实看到MainWindowResource.cs中的值,但是当我在MainWindow代码隐藏中获得类的实例并且我更改箭头的值时,箭头路径无法识别更改,因此它不能是同一个实例。

我尝试为箭头创建一个单独的类文件,我在MainWindow的代码隐藏中得到了该类的实例,如下所示:

    private MainWindowResource _mainWindowResource = null;
    private ArrowResource _arrowResource = null;
. . .
        _mainWindowResource = (MainWindowResource)this.Resources["MainWindowResource"];
        _arrowResource = (ArrowResource)Application.Current.Resources["ArrowResource"];

但是当我尝试更改ArrowResource类(ArrowResources.xaml中资源字典的支持类)中的值时,我可以更改值,但它们仍未反映在箭头路径中。

有没有人知道如何从代码隐藏中更改这些值?

1 个答案:

答案 0 :(得分:1)

将我的评论转换为答案。

将公共构造函数添加到MainWindowResource类,例如:

public MainWindowResource() {
  Debug.WriteLine("Called");
}

并查看它被调用了多少次。我猜是两个。一个稍微棘手的事情是,重新定义资源不会导致新的对象创建,直到所述资源实际用于子范围。

在您的情况下,您可以从MainWindow中删除资源重复定义,就像它在App.xaml中声明的那样(通过ResourceDictionary),它已经可用于MainWindow.xaml,使重新定义毫无意义。