Prism使用中的事件聚合器给出异常

时间:2017-07-25 04:30:03

标签: wpf prism

我必须在2个视图模型之间进行通信,所以我使用的是事件聚合器,但我观察到该方法在更新属性时调用了2次,并且第一次它按预期工作但第二次所有元素都为null并且抛出null引用异常。

为什么会发生这种情况我没有第二次触发它。

MainViewModel

 private XMLNode NodeSelected;

    public XMLNode NodeSelected
    {
        get { return NodeSelected; }
        set
        {
            nodeSelected = value;
            iEventAggregator.GetEvent<AddNewObjectEvent>().Publish(this.NodeSelected);

        }
    }

UsercontrolViewModel

 public UserControlViewModel(IEventAggregator iEventAggregator)
    {
        this.iEventAggregator = iEventAggregator;
        this.iEventAggregator.GetEvent<AddNewGuiSyncObjectEvent>()
    .Subscribe(AddXMLNode);
    }

AddXMLNODE方法相关代码

 private void AddXMLNODE (XMLNode SelectedNode)
    {
        if (this.CriteriaItem == null) return;
        SyncObject currentObj = new SyncObject(SelectedNode);
        if (!IsSyncItemNameUnique(currentObj))
        {
            currentObj.Name = GetUniqueName(currentObj);
        }
        this.CriteriaItem.SyncObjects.Add(currentObj);
        this.SelectedSyncObject = this.CriteriaItem .SyncObjects.LastOrDefault();
    }

这里第一次“CriteriaItem”正确并且newnode被添加到集合中但是同样的方法再次命中并且CriteriaItem为NULL如果我删除那个空检查我们将获得异常。

我没有得到什么错误。

完整的代码

UserControl ViewModel

namespace Hexagon.SmartUITest.GUISynchronization.ViewModel
{
    public class IndividualSyncViewModel : ViewModelBase
    {
        #region properties
        private GUISyncObject selectedSyncObject;
        public GUISyncObject SelectedSyncObject
        {
            get { return selectedSyncObject; }
            set
            {
                selectedSyncObject = value;
                this.OnPropertyChanged(() => this.SelectedSyncObject);
                iEventAggregator.GetEvent<SelectedSyncObjectEvent>().Publish(this.SelectedSyncObject);
            }
        }
        private SyncCriteriaItem _CriteriaItem;

        public SyncCriteriaItem CriteriaItem
        {
            get { return CriteriaItem; }
            set
            {
               CriteriaItem = value;
                OnPropertyChanged(() => this.CriteriaItem);
            }
        }

        private IEventAggregator iEventAggregator;
        #endregion

        #region constructor
        public IndividualSyncViewModel(IEventAggregator iEventAggregator)
        {
            this.iEventAggregator = iEventAggregator;
            this.iEventAggregator.GetEvent<AddNewGuiSyncObjectEvent>()
             .Subscribe(AddGUISyncItem);
        }

        #endregion



        private ICommand deleteSyncObjectClick;

        public ICommand DeleteSyncObjectClick
        {
            get
            {
                if (deleteSyncObjectClick == null) deleteSyncObjectClick = new RelayCommand(DeleteSync);
                return deleteSyncObjectClick;
            }
            set
            {
                deleteSyncObjectClick = value;
            }
        }
        private void DeleteSync()
        {
            this.CriteriaItem.SyncObjects.Remove(selectedSyncObject);
            selectedSyncObject = this.CriteriaItem.SyncObjects.LastOrDefault();
        }


        private bool IsItemNameUnique(GUISyncObject SyncObject)
        {
            if (this.CriteriaItem != null && this.CriteriaItem.SyncObjects.Count == 0)
                return true;

            foreach (GUISyncObject item in this.CriteriaItem.SyncObjects.ToList())
            {
                if (item.Name.Equals(SyncObject.Name) && !item.CommandNodeName.Equals(SyncObject.CommandNodeName))
                    return false;
            }
            return true;
        }
        private string GetUniqueName(GUISyncObject syncItem)
        {
            List<string> itemsNames = this.CriteriaItem.SyncObjects.Select(item => item.Name).ToList();
            return CommonNamingRules.GetUniqueName(itemsNames, syncItem.Name);
        }

        private void AddGUISyncItem(ControlNode SelectedNode)
        {
            if (this.CriteriaItem == null) return;
            GUISyncObject currentObj = new GUISyncObject(SelectedNode);
            if (!IsSyncItemNameUnique(currentObj))
            {
                currentObj.Name = GetUniqueName(currentObj);
            }
            this.CriteriaItem.SyncObjects.Add(currentObj);
            this.SelectedSyncObject = this.CriteriaItem.SyncObjects.LastOrDefault();
        }

    }
}

UserControl xaml.cs

public partial class IndividualSync : UserControl
{
    private IndividualSyncViewModel _vm;
    public IndividualSync()
    {
        InitializeComponent();
         _vm = new IndividualSyncViewModel(Event.EventInstance.EventAggregator);
        rootGrid.DataContext = _vm;           
    }
    #region properties

    public SyncCriteriaItem SyncCriteriaItem
    {
        get { return (SyncCriteriaItem)GetValue(SyncCriteriaItemProperty); }
        set { SetValue(SyncCriteriaItemProperty, value); }
    }

    public static readonly DependencyProperty SyncCriteriaItemProperty = DependencyProperty.Register("SyncCriteriaItem", typeof(SyncCriteriaItem), typeof(IndividualSync), new PropertyMetadata(null, OnCriteriaItemSet));

    public GUISyncObject SelectedSYNC
    {
        get { return (GUISyncObject)GetValue(SelectedSYNCDependencyProperty); }
        set { SetValue(SelectedSYNCDependencyProperty, value); }
    }

    public static readonly DependencyProperty SelectedSYNCDependencyProperty = DependencyProperty.Register("SelectedSYNC", typeof(GUISyncObject), typeof(IndividualSync), new PropertyMetadata(null, OnGUISyncItemSelect));

    private static void OnCriteriaItemSet(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        ((IndividualSync)d)._vm.CriteriaItem = e.NewValue as SyncCriteriaItem;
    }

    private static void OnSyncItemSelect(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
       ((IndividualSync)d)._vm.SelectedSyncObject = e.NewValue as GUISyncObject;
    }
    #endregion


}

Iam在usercontrol上创建两个依赖项属性,这些属性将从父usercontrol设置。

父用户控件Xaml

  <UserControl.Resources>
    <Converters:IndexToTabNameConverter x:Key="TabIndexConverter"/>
    <DataTemplate x:Key="SyncTabItemTemplate" >
        <StackPanel VerticalAlignment="Center"
            Orientation="Horizontal">
            <TextBlock  Text="{Binding Converter={StaticResource TabIndexConverter},
              RelativeSource={RelativeSource AncestorType={x:Type telerik:RadTabItem}}}"/>
            <Button Margin="10,0,0,0"              
          Style="{StaticResource CloseButton}"
          ToolTipService.ToolTip="Save and Close">
                <Button.Content>
                    <Path Data="M0,0 L6,6 M6, 0 L0,6"
            SnapsToDevicePixels="True"
            Stroke="Black"
            StrokeThickness="1" />
                </Button.Content>
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="Click">
                        <uxt:EventToCommand  CommandParameter="{Binding}" Command="{Binding Path=DataContext.RemoveSyncCriteriaCommand,ElementName=rootGrid}" />
                    </i:EventTrigger>
                </i:Interaction.Triggers>
            </Button>
        </StackPanel>
    </DataTemplate>       
    <DataTemplate x:Key="EmptyTemplate">
        <TextBlock FontWeight="Bold" FontFamily="Comic Sans" FontStyle="Italic" Text="{Binding}" />
    </DataTemplate>
    <DataTemplate x:Key="HeaderTemplate">
        <Label FontWeight="Bold"  HorizontalContentAlignment="Center" Content="{Binding}" />
    </DataTemplate>
    <DataTemplate x:Key="SyncCriteriaTemplate">
        <local:IndividualSync SyncCriteriaItem="{Binding}" SelectedGUISYNC="{Binding Path=DataContext.SelectedGUISYNCOBJECT}"/>
    </DataTemplate>        
    <DataTemplate x:Key="newTabButtonHeaderTemplate">         
        <telerik:RadButton Style="{DynamicResource IconButtonStyle}" Width="20" Height="20" Command="{Binding Path=DataContext.NewCommand,ElementName=rootGrid}" ToolTip="Click to add new item">
            <uxt:UxtXamlImage Template="{DynamicResource Com_Add}" />
        </telerik:RadButton>
    </DataTemplate>
    <DataTemplate x:Key="itemContentTemplate">
        <Grid/>
    </DataTemplate>
    <Selectors:TabItemTemplateSelector x:Key="headerTemplateSelector"
                       NewButtonTemplate="{StaticResource newTabButtonHeaderTemplate}"
                       ItemTemplate="{StaticResource SyncTabItemTemplate}"/>
    <Selectors:TabItemTemplateSelector x:Key="contentTemplateSelector"
                        NewButtonTemplate="{StaticResource itemContentTemplate}"
                        ItemTemplate="{StaticResource SyncCriteriaTemplate}"/>
    <Selectors:SyncTemplateSelector x:Key="syncTemplates">          
        <Selectors:SyncTemplateSelector.ProcessSyncTemplate>
            <DataTemplate>
                <telerik:Label Content="{Binding ProcessSync,StringFormat={}{0}}"  BorderThickness="1"  HorizontalContentAlignment="Left"  FontStyle="Oblique" Width="{Binding Width,RelativeSource={RelativeSource AncestorType=telerik:RadListBox}}"/>
            </DataTemplate>
        </Selectors:SyncTemplateSelector.ProcessSyncTemplate>
        <Selectors:SyncTemplateSelector.GUISyncTemplate>
            <DataTemplate>
                <Expander Header="GUISYNC" HeaderTemplate="{StaticResource HeaderTemplate}" Width="{Binding Width,RelativeSource={RelativeSource AncestorType=telerik:RadListBox}}"  IsExpanded="{Binding Mode=TwoWay, Path=IsSelected, RelativeSource={RelativeSource AncestorType=telerik:RadListBoxItem, Mode=FindAncestor}}">
                    <telerik:RadTabControl  ItemsSource="{Binding SyncCriteriaItem}" OverflowMode="Scroll"  DropDownDisplayMode="Visible"   SelectedItem="{Binding SelectedSyncCriteria, Mode=TwoWay}" SelectedIndex="0"
                                          ItemTemplateSelector="{StaticResource headerTemplateSelector}"
                        ContentTemplateSelector="{StaticResource contentTemplateSelector}">                           
                    </telerik:RadTabControl>
                </Expander>                   
            </DataTemplate>
        </Selectors:SyncTemplateSelector.GUISyncTemplate>           
    </Selectors:SyncTemplateSelector>      
</UserControl.Resources>    

      <Grid Name="rootGrid">
    <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="auto"/>
    </Grid.ColumnDefinitions>
    <telerik:RadListBox Margin="20,5,20,0" Grid.Row="0" Grid.Column="0" Name="synclist"  ItemsSource="{Binding CurrentSyncObjectCollection.SyncObjects}"  ItemTemplateSelector="{StaticResource syncTemplates}" SelectedItem="{Binding SelectedSyncObject,Mode=TwoWay}" >            
    </telerik:RadListBox>
    <telerik:RadComboBox  Grid.Row="1" Grid.Column="0" Name="SyncOption" EmptyText="Select a sync type to be added " Margin="0,8,0,5"  EmptySelectionBoxTemplate="{StaticResource EmptyTemplate}" ItemsSource="{Binding SyncTypes}"  Width="{Binding ActualWidth, ElementName=synclist}" HorizontalContentAlignment="Center" Height="25" SelectedIndex="{Binding SelectedSyncIndex,Mode=TwoWay}">
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="SelectionChanged">
                <uxt:EventToCommand Command="{Binding AddSelectedSyncClick}" CommandParameter="{Binding Path=SelectedValue,ElementName=SyncOption}"/>
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </telerik:RadComboBox>
    <telerik:RadButton Style="{DynamicResource IconButtonStyle}" Grid.Column="1" Grid.Row="0" Width="20" Height="20" VerticalAlignment="Top" IsEnabled="{Binding Path=SelectedSyncObject,Converter={uxt:ObjectToBoolConverter}}"  ToolTip="Click to delete selected Sync"                            
                           Command="{Binding DeleteSyncObjectClick}">
        <uxt:UxtXamlImage Template="{DynamicResource Com_Delete}" />
    </telerik:RadButton>
</Grid>

我希望这会有所帮助。我已经调试了代码,我观察到甚至两个项目被绑定为CriteriaItems Breakpoint命中依赖属性标准项目3次,并且一次null。

即使我更改Tab选项依赖属性设置代码是2次而不是1次。第一次为null设置CriteriaItem并且第二次相应的项目即将到来。

0 个答案:

没有答案