0

我遇到了与此 SO question中描述的类似的问题。建议的解决方案是为我们希望呈现的每个现在页面 (PDF) 创建一个新的 WebBrowser 控件(覆盖旧的 WebBrowser 控件)。在 MVVM 中创建新控件的正确方法是什么?我试图让 VM 对视图的实现一无所知。

4

3 回答 3

1

为什么 VM 需要知道?为什么视图不能挂钩到一个适当的事件(如果你喜欢定义一个,或者只是使用PropertyChanged)并重新创建控件?

于 2012-04-17T06:20:41.117 回答
1
  1. 在 ViewModel 中创建一个名为 IBrowserCreator 的接口,并使用一个名为 CreateBrowser() 的方法。
  2. 在 ViewModel 中创建一个名为 ViewHelper 的静态类,并向其添加一个名为 BrowserCreator 的 IBrowserCreator 类型的静态属性。
  3. 在 View 层中,创建一个名为 BrowserCreator 的新类,该类实现 ViewModel.IBrowserCreator。
  4. 在 View 初始化代码中,实例化一个 BrowserCreator,并将其分配给 ViewModel.ViewHelper.BrowserCreator。

从您的 ViewModel,您现在应该可以调用:

ViewHelper.BrowserCreator.CreateBrowser()

显然这个答案只是一个框架,但它应该给你一个大致的想法。您需要实现 CreateBrowser 方法以满足您的确切需求。

于 2012-04-17T06:21:42.477 回答
0

为什么不简单地使用 Datatemplate 并让 WPF 完成剩下的工作呢?

  1. 使用网络浏览器创建用户控件。您必须添加附加属性,因为您不能直接绑定到源。

    <UserControl x:Class="WpfBrowser.BrowserControl"
             xmlns:WpfBrowser="clr-namespace:WpfBrowser" >
      <Grid>
        <WebBrowser WpfBrowser:WebBrowserUtility.BindableSource="{Binding MyPdf}"/>
      </Grid>
    </UserControl>
    
  2. 创建一个处理您的uri的视图模型

    public class MyPdfVM
    {
      public Uri MyPdf { get; set; }
    
      public MyPdfVM()
      {
        this.MyPdf = new Uri(@"mypdf path"); 
      }
    }
    
  3. 获取您的 pageviewmodel,添加 pdfviewmodel 并在您的视图中获取内容控件

    public class MyPageViewmodel: INotifyPropertyChanged
    {
      private MyPdfVM _myPdfStuff;
      public MyPdfVM MyPdfStuff
      {
        get { return _myPdfStuff; }
        set { _myPdfStuff = value; this.NotifyPropertyChanged(()=>this.MyPdfStuff);}
      }
    
      public MyViewmodel()
      {
        this.MyPdfStuff = new MyPdfVM();
      }
    
      public event PropertyChangedEventHandler PropertyChanged;
      protected void NotifyPropertyChanged<T>(Expression<Func<T>> property)
      {
        var propertyInfo = ((MemberExpression)property.Body).Member as PropertyInfo;
    
        if (propertyInfo == null)
        {
            throw new ArgumentException("The lambda expression 'property' should point to a valid Property");
        }
    
        var handler = PropertyChanged;
    
        if (handler != null)
            handler(this, new PropertyChangedEventArgs(propertyInfo.Name));
      }
    }
    

窗口.xaml

    <Window x:Class="WpfBrowser.MainWindow"
            xmlns:WpfBrowser="clr-namespace:WpfBrowser" 
            Title="MainWindow" Height="350" Width="525">
     <Window.Resources>
       <DataTemplate DataType="{x:Type WpfBrowser:MyPdfVM}">
        <WpfBrowser:BrowserControl />
       </DataTemplate>
     </Window.Resources>
     <Grid>
       <Grid.RowDefinitions>
        <RowDefinition Height="64*" />
        <RowDefinition Height="247*" />
       </Grid.RowDefinitions>
      <Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="32,14,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" />
      <ContentControl Grid.Row="1" Content="{Binding MyPdfStuff}"/>
     </Grid>
    </Window>

窗口.xaml.cs

public partial class MainWindow : Window
{
    private MyViewmodel _data;
    public MainWindow()
    {
        _data = new MyViewmodel();
        InitializeComponent();
        this.DataContext = _data;
    }

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        this._data.MyPdfStuff = new MyPdfVM() { MyPdf = new Uri(@"your other pdf path for testing") };
    }
}

每当您更改 MyPdfStuff 属性时,网络浏览器都会更新 pdf。

附属财产

public static class WebBrowserUtility
{
    public static readonly DependencyProperty BindableSourceProperty =
        DependencyProperty.RegisterAttached("BindableSource", typeof(string), typeof(WebBrowserUtility), new UIPropertyMetadata(null, 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.IsNullOrWhiteSpace(uri) ? null:new Uri(uri);
        }
    }

}

编辑:添加了一些代码,因此您可以看到,如果您更改 PDFViewmodel,您的浏览器控件将显示新的 pdf。

于 2012-04-17T06:57:54.533 回答