在WPF的TabItem的WebBrowser,MVVM的DataTemplate中绑定事件

时间:2016-09-23 16:26:18

标签: c# wpf events mvvm datatemplate

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

当我尝试使用Expression混合交互库在MvvmLight方式中正常执行此操作时,一个例外就会出现:

  

错误集合属性   '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没有路由事件,但问题是一样的,如何绑定到它的事件?

1 个答案:

答案 0 :(得分:0)

如果在模板中绑定事件或使用表达式混合交互库是不可能的话,请回答

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=

相关问题