WPF's TabItem's WebBrowser, MVVM的DataTemplate事件绑定

本文关键字:DataTemplate 事件 绑定 WebBrowser TabItem WPF MVVM | 更新日期: 2023-09-27 18:08:27

问题是:如何将WebBrowser的任何事件绑定到ItemTemplate内的视图模型中的ICommand属性?

当我试图使用表达式混合交互库在正常MvvmLight方式做到这一点时,发生异常:

错误收集属性"Microsoft.VisualStudio.DesignTools.WpfDesigner.InstanceBuilders.HwndHostInstance"。"触发"是零。

WebTabItems是项的可观察集合

代码如下:

 <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。导航不是路由事件,但问题是一样的,如何绑定到它的事件?

WPF's TabItem's WebBrowser, MVVM的DataTemplate事件绑定

已经找到了如何在模板中绑定事件的答案,或者当使用Expression混合交互库是不可能的

ICommand类型的附加属性是实现相同功能的另一种方式。

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

在我的例子中:XAML

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

分隔类添加附加的依赖属性到原来的web浏览器

 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 =