我遇到的问题与in this SO question所描述的类似。建议的解决方案是为我们希望呈现的每个现在页面(PDF)创建一个新的WebBrowser控件(覆盖旧的WebBrowser控件)。 在MVVM中创建新控件的正确方法是什么?我试图让VM无视视图的实现。
答案 0 :(得分:1)
为什么VM需要知道?为什么视图不能挂钩到适当的事件(如果你愿意定义一个,或者只是使用PropertyChanged
)并重新创建控件?
答案 1 :(得分:1)
现在,您应该可以从ViewModel调用:
ViewHelper.BrowserCreator.CreateBrowser()
显然这个答案只是一个框架,但它应该给你一般的想法。您需要实现CreateBrowser方法以满足您的确切需求。
答案 2 :(得分:0)
为什么不简单地使用Datatemplate让WPF完成剩下的工作呢?
使用webbrowser创建用户控件。您必须添加附加属性,因为您无法直接绑定到源。
<UserControl x:Class="WpfBrowser.BrowserControl"
xmlns:WpfBrowser="clr-namespace:WpfBrowser" >
<Grid>
<WebBrowser WpfBrowser:WebBrowserUtility.BindableSource="{Binding MyPdf}"/>
</Grid>
</UserControl>
创建一个处理你的uri的viewmodel
public class MyPdfVM
{
public Uri MyPdf { get; set; }
public MyPdfVM()
{
this.MyPdf = new Uri(@"mypdf path");
}
}
获取您的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));
}
}
window.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>
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属性时,webbroswer会更新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,您的browsercontrol会显示新的pdf。