1

在开始之前,我已经在 GIST 中添加了与我的问题相关的文件:https ://gist.github.com/4468651

正如标题所说,我有一个 WPF 应用程序(实现 MVVM - 或者尽可能地成为初学者),并且MainView的 Visibility 属性绑定似乎没有从它的ViewModel中提取相关值。

在启动时,会抛出一个绑定错误,表明它在实例化时没有找到ViewModel(即使它已传递给构造函数)。错误如下:

System.Windows.Data Error: 23 : Cannot convert '<null>' from type '<null>' to 
type 'System.Windows.Visibility' for 'en-US' culture with default conversions; 
consider using Converter property of Binding. 

NotSupportedException:'System.NotSupportedException: EnumConverter cannot 
convert from (null).
at System.ComponentModel.TypeConverter.GetConvertFromException(Object value)
at System.ComponentModel.EnumConverter.ConvertFrom(ITypeDescriptorContext context, 
CultureInfo culture, Object value)
at MS.Internal.Data.DefaultValueConverter.ConvertHelper(Object o, Type destinationType, 
DependencyObject targetElement, CultureInfo culture, Boolean isForward)'  

我尝试将TargetNullValueNullConverter添加到绑定中,但这并没有减轻警告或问题。我还尝试直接更改为提供System.Windows.Visibility值的属性,以使用数据触发器检查布尔属性并相应地设置可见性,这也没有改变问题或警告消息。

加载完所有内容后,如果我在托盘图标上调出上下文菜单并单击“*隐藏窗口”或“显示窗口” (它应该通知MainView它需要隐藏或显示)什么都不会发生。这就是我m 期望在代码中发生(仅引用与问题相关的文件):

App.xaml.cs 文件 -

namespace ordoFile
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : Application
    {

        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);

            this.Properties["bgStartup"] = false;

            if (e != null && e.Args.Count() > 0)
            {
                if(e.Args[0] == "-bg")
                {
                    this.Properties["bgStartup"] = true;
                }
            }

            Configs configs = new Configs();
            PresetFilters presets = new PresetFilters();
            OrganisationSyncer organisationSyncer = new OrganisationSyncer();
            TrayApp trayApp = new TrayApp(organisationSyncer, configs);
            Logger logger = new Logger();
            BackgroundOrganiser backgroundOrganiser = new BackgroundOrganiser(new DirectoryModel());
            ForegroundOrganiser foregroundOrganiser = new ForegroundOrganiser(new DirectoryModel());

            DependencyFactory.Container.RegisterInstance<Configs>("configs", configs);
            DependencyFactory.Container.RegisterInstance<PresetFilters>("presets", presets);
            DependencyFactory.Container.RegisterInstance<OrganisationSyncer>("organisationSyncer", organisationSyncer);
            DependencyFactory.Container.RegisterInstance<BackgroundOrganiser>("backgroundOrganiser", backgroundOrganiser);
            DependencyFactory.Container.RegisterInstance<ForegroundOrganiser>("foregroundOrganiser", foregroundOrganiser);
            DependencyFactory.Container.RegisterInstance<TrayApp>("trayApp", trayApp);
            DependencyFactory.Container.RegisterInstance<Logger>("logger", logger);

            MainViewModel mainViewModel = new MainViewModel(trayApp, organisationSyncer);
            MainView mainView = new MainView(configs, trayApp, mainViewModel);

            mainView.Show();
        }
    }
}

mainViewModel变量通过this.DataContext = mainViewModel在MainView实例的构造函数中设置

MainView.xaml

<Window x:Class="ordoFile.Views.MainView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:vm="clr-namespace:ordoFile.ViewModels"
        xmlns:vw="clr-namespace:ordoFile.Views"
        Title="ordoFile" 
        Name="MainWindow"
        Height="500" 
        Width="815">

    <Window.Style>
        <Style TargetType="Window">
            <Setter Property="Visibility" Value="{Binding WindowVisibility}"  />
        </Style>
    </Window.Style>

    <Grid Name="ContentGrid">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"></RowDefinition>
            <RowDefinition Height="*"></RowDefinition>
            <RowDefinition Height="*"></RowDefinition>
        </Grid.RowDefinitions>

        <vw:ForegroundOrganiserView Grid.RowSpan="2"/>

        <vw:BackgroundOrganiserView Grid.Row="2"/>
    </Grid>
</Window>

MainViewModel.cs

namespace ordoFile.ViewModels
{
    public class MainViewModel : ViewModelBase
    {
        TrayApp _trayApp;

        OrganisationSyncer _organisationSyncer;

        Visibility _windowVisibility;

        public MainViewModel(TrayApp trayApp, OrganisationSyncer organisationSyncer)
        {
            _trayApp = trayApp;
            _organisationSyncer = organisationSyncer;
            OnInitialise();
        }

        /// <summary>
                    /// Return visibilty staus of MainView
                    /// </summary>
        public Visibility WindowVisibility
        {
            get { return _windowVisibility; }
            set
            {
                _windowVisibility = value;
                OnPropertyChanged("WindowVisibility");
            }
        }

        void OnInitialise()
        {
            WindowVisibility = _organisationSyncer.WindowVisibilty;

            // Add method to event handler in OrganisationSyncer
            // that will be called when UI visibility is to be updated.
            _organisationSyncer.UpdateWindowVisibility += CheckVisibilityStatus;
        }

        /// <summary>
        /// Set property to visibility value held in OrganisationSyncer
        /// instance.
        /// </summary>
        void CheckVisibilityStatus(object sender, EventArgs e)
        {
            WindowVisibility = _organisationSyncer.WindowVisibilty;
        }
    }
}

所有这些似乎工作正常,调用了 setter,并且 UI 甚至尝试读取它(我通过在更新发生后抛出的 getter 中抛出异常来检查这一点)。

我很茫然,希望有任何意见!

ps https://www.dropbox.com/s/03z361qyws4jhuo/ordoFile.zip是项目文件的链接,如果有人想修改实际项目,因为我确信我没有特别清楚地解释这个问题。

Uodate(感谢 Backlash):我之前提到的错误似乎与我的MainView可见性未正确更新的问题无关。

4

2 回答 2

4

从逐步开始,错误是这一行:

<Setter Property="Visibility" Value="{Binding WaitImageVisibility}" />

您的 WaitImageVisibility 是一个字符串值。您需要将其更改为 Visibility 类型(顺便说一下,您通常不会将 Visibility 用作视图模型上的数据类型,但这没什么大不了的),或者您需要一个从字符串转换的转换器到能见度。

于 2013-01-06T21:18:23.393 回答
0

似乎没有将绑定模式设置为TwoWay导致了我的问题。

于 2013-01-09T16:58:08.053 回答