2012-04-17 4 views
0

in this SO questionと同様の問題が発生しました。提案されている解決策は、表示する各現在のページ(PDF)に対して新しいWebBrowserコントロールを作成することです(古いWebBrowserコントロールを上書きする)。 MVVMのような新しいコントロールを作成する正しい方法は何ですか?私はVMのビューの実装については無知を維持しようとしています。MVVMに違反することなくビュー内にコントロールの新しいインスタンスを作成するには

答えて

1

なぜVMは知る必要がありますか?なぜ、ビューが適切なイベントにフックすることができないのですか(好きな場合は定義するか、PropertyChangedを使用するだけです)、コントロールを再作成するのはなぜですか?

+0

ええ、それはMVVMの本当の意味です。このアプローチの正しさを証明する別のアイデアを追加したいと思います。 OPのある時点で、OPがパネルやウィンドウ、あるいはWebブラウザの代わりに何かにコンテンツを表示する必要があると判断した場合、変更する唯一のものは小さなコードですそのコンテンツをどのように表示するかを決定するビューに表示されます。 VMは元のままです。 –

1
  1. ViewModelで、CreateBrowser()というメソッドを使用して、IBrowserCreatorという名前のインターフェイスを作成します。
  2. ViewHelperというViewModelで静的クラスを作成し、BrowserCreatorという名前のIBrowserCreator型の静的プロパティを追加します。
  3. Viewレイヤーで、ViewModel.IBrowserCreatorを実装するBrowserCreatorという新しいクラスを作成します。
  4. View初期化コードで、BrowserCreatorをインスタンス化し、ViewModel.ViewHelper.BrowserCreatorに割り当てます。あなたのViewModelから

、あなたが今呼び出すことができるはずです。

ViewHelper.BrowserCreator.CreateBrowser()

明らかにこの答えは唯一のフレームワークですが、それはあなたの一般的なアイデアを与える必要があります。正確なニーズに合わせてCreateBrowserメソッドを実装する必要があります。

+0

ありがとう!私はこのソリューションが本当に好きですが、私はケント・ブーガートが提案しているより単純なアプローチを忘れていて、私の場合には可能です。 – OSH

+0

私が実際にこのソリューションで気に入らないのは、静的なプロパティを持つことです。 VMとVのインスタンスが同時に複数ある場合はどうなりますか?場合によっては解決策が適切かもしれませんが、私はそれをお勧めしません。 Kent Boogaartの方法は、よりシンプルで柔軟性があります。 –

0

単にDatatemplateを使用してWPFに残りの処理をさせてみませんか?

  1. webbrowserでusercontrolを作成します。直接ソースにバインドすることはできないため、接続プロパティを追加する必要があります。

    <UserControl x:Class="WpfBrowser.BrowserControl" 
         xmlns:WpfBrowser="clr-namespace:WpfBrowser" > 
        <Grid> 
        <WebBrowser WpfBrowser:WebBrowserUtility.BindableSource="{Binding MyPdf}"/> 
        </Grid> 
    </UserControl> 
    
  2. 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)); 
        } 
    } 
    

window.xamlをContentControlにを取るあなたのURIを扱うのviewmodelを作成します

あなたがMyPdfStuffプロパティを変更史上webbroswerは、PDFを更新
<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") }; 
    } 
} 

添付プロパティ

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); 
     } 
    } 

} 

EDIT:あなたはあなたがPDFViewmodel chane場合は、あなたのbrowsercontrolは新しいPDFを表示することを見ることができるようにいくつかのコードを追加しました。

+0

これは動作しません。ブラウザでURLを変更すると例外がスローされます。私が参照した他のSOの質問を見てください。 – OSH

+0

チャーミーのように機能します。私はあなたの自己を試すことができるようにいくつかのコードを追加します。 – blindmeis

関連する問題