【问题标题】:Binding of event in DataTemplate of WPF's TabItem's WebBrowser, MVVMWPF的TabItem的WebBrowser、MVVM的DataTemplate中的事件绑定
【发布时间】:2016-09-23 16:26:18
【问题描述】:

问题是:如何将 WebBrowser 的任何事件绑定到 ItemTemplate 内的 View Model 中的 ICommand 属性?

当我尝试以 MvvmLight 方式正常使用 Expression blend 交互库执行此操作时,会出现异常:

错误集合属性 'Microsoft.VisualStudio.DesignTools.WpfDesigner.InstanceBuilders.HwndHostInstance'。'触发器' 为空。

WebTabItems 是项目 ViewModels 的可观察集合

代码如下:

 <TabControl  ItemsSource="{Binding WebTabItems}" SelectedItem="{Binding SelectedWebTabItem}" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" >
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="SelectionChanged">
                        <mvvm:EventToCommand Command="{Binding SelectionChangedVMCommand}" PassEventArgsToCommand="True"></mvvm:EventToCommand>
                    </i:EventTrigger>
                </i:Interaction.Triggers>

                <TabControl.ItemTemplate>
                    <!--header-->
                    <DataTemplate>
                        <TextBlock Text="{Binding Header}"></TextBlock>                            
                    </DataTemplate>                        
                </TabControl.ItemTemplate>
                <TabControl.ContentTemplate>
                    <DataTemplate>                        
                        <Grid >
                            <Grid.RowDefinitions>
                                <RowDefinition Height="auto"></RowDefinition>
                                <RowDefinition></RowDefinition>
                            </Grid.RowDefinitions>

                            <TextBlock Text="{Binding NotificationRibbonText}" Visibility="{Binding NotificationRibbonVisibility}"></TextBlock>


                            <WebBrowser Grid.Row="1" Visibility="Visible" local:WebBrowserExtension.BindableSource="{Binding Sourse}" >
                                <i:Interaction.Triggers>
                                    <i:EventTrigger EventName="Navigating">
                                        <mvvm:EventToCommand Command="{Binding NavigatingMVCommand}" PassEventArgsToCommand="True" ></mvvm:EventToCommand>
                                    </i:EventTrigger>
                                </i:Interaction.Triggers>
                            </WebBrowser>



                        </Grid>
                    </DataTemplate>
                </TabControl.ContentTemplate>

            </TabControl>

选项卡控件中的事件绑定效果很好,但在模板中却不行

xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
                                   <i:Interaction.Triggers>
                                        <i:EventTrigger EventName="Navigating">
                                            <mvvm:EventToCommand Command="{Binding NavigatingMVCommand}" PassEventArgsToCommand="True" ></mvvm:EventToCommand>
                                        </i:EventTrigger>
                                    </i:Interaction.Triggers>

Ps 问题可能是WebBrowser.Navigating 不是路由事件,但是问题是一样的,如何绑定到它的事件?

【问题讨论】:

    标签: c# wpf events mvvm datatemplate


    【解决方案1】:

    找到了如何在模板中绑定事件或使用表达式混合交互库时不可能的答案

    ICommand 类型的附加属性是实现相同功能的其他方式。

    这个答案也可以用于绑定到非路由事件

    就我而言: XAML

      <WebBrowser Grid.Row="1" Visibility="Visible" 
                                            local:WebBrowserExtension.BindableSource="{Binding NavigeteToSourse}" 
                                            local:WebBrowserExtension.NavigatingCmdExtended="{Binding NavigatingMVCommand}" 
    
                                            >
    
                                </WebBrowser>
    

    将附加依赖属性添加到原始网络浏览器的分离类

     class WebBrowserExtension
        {
    
        #region BindableSourceProperty
    
        public static readonly DependencyProperty BindableSourceProperty =
        DependencyProperty.RegisterAttached("BindableSource", typeof(string), typeof(WebBrowserExtension), new UIPropertyMetadata("", BindableSourcePropertyChanged));
    
        public static string GetBindableSource(DependencyObject obj)
        {
            return (string)obj.GetValue(BindableSourceProperty);
        }
    
        public static void SetBindableSource(DependencyObject obj, string value)
        {
            obj.SetValue(BindableSourceProperty, value);
        }
    
        public static void BindableSourcePropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
        {
            WebBrowser browser = o as WebBrowser;
            if (browser != null)
            {
                string uri = e.NewValue as string;
                browser.Source = !String.IsNullOrEmpty(uri) ? new Uri(uri) : null;
            }
        }
        #endregion
    
            #region NavigatingCmdExtended
    
            public static ICommand GetNavigatingCmdExtended(DependencyObject obj)
            {
                return (ICommand)obj.GetValue(NavigatingCmdExtendedProperty);
            }
            public static void SetNavigatingCmdExtended(DependencyObject obj, ICommand value)
            {
                obj.SetValue(NavigatingCmdExtendedProperty, value);
            }
            // Using a DependencyProperty as the backing store for CalenderOpenCommand. This enables animation, styling, binding, etc...
            public static readonly DependencyProperty NavigatingCmdExtendedProperty =
            DependencyProperty.RegisterAttached("NavigatingCmdExtended", typeof(ICommand), typeof(WebBrowserExtension), new PropertyMetadata(OnChangedNavigatingCmdExtendedProperty));
    
    
            private static void OnChangedNavigatingCmdExtendedProperty(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                var webBrowser = d as WebBrowser;
                if (webBrowser != null)
                {
                    if (e.NewValue != null)
                    {
                        //attach event handler
                        webBrowser.Navigating += webBrowser_Navigating;
                    }
                    else
                    {
                        //detach event handler
                        webBrowser.Navigating -= webBrowser_Navigating;
                    }
                }
            }
            ///
            /// Event handler for Calender Opened event.
            ///
            ///
            ///
            static void webBrowser_Navigating(object sender, NavigatingCancelEventArgs e)
            {
                ICommand command = GetNavigatingCmdExtended(sender as DependencyObject);
                if (command != null)
                {
                    if (command.CanExecute(e))
                    {
                        //executes a command
                        command.Execute(e);
                    }
                }
            }
            #endregion
    

    ViewModel 中的命令

    public class WebTabItemVievModel: ViewModelBase
    {
    
        public WebTabItemVievModel()
        {
    
            NavigatingMVCommand = new RelayCommand<NavigatingCancelEventArgs>(NavigatingMethod);
    
        }
    
    
    
        public ICommand NavigatingMVCommand { get;  set; }
        private void NavigatingMethod(NavigatingCancelEventArgs e)
        {
            Messenger.Default.Send<NotificationMessage <UriChangedMSG>>(new NotificationMessage<UriChangedMSG> (new UriChangedMSG { NewUri = e.Uri.AbsoluteUri },"test"));
            CurrentUri = e.Uri.AbsoluteUri;
            NotificationRibbonText = e.Uri.AbsoluteUri;
        }
    

    详情请参考这篇文章:

    http://www.codeproblem.com/articles/frameworks/wpf/87-event-to-command-binding-using-attached-properties-in-plain-wpf-without-any-extra-dependancy?showall=1&limitstart=

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-02-04
      • 2013-08-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多