1

私はWPF MVVMアプリケーションに取り組んでいます。WebBrowser コントロールを、タブにバインドされているビュー モデルにデータバインドしようとしています。この記事のアドバイスに従って、静的な DependancyProperty で構成される静的ヘルパー クラスを作成しました。

public static class WebBrowserHelper
{
    public static readonly DependencyProperty BodyProperty =
        DependencyProperty.RegisterAttached("Body", typeof(string), typeof(WebBrowserHelper), new PropertyMetadata(OnBodyChanged));

    public static string GetBody(DependencyObject dependencyObject)
    {
        return (string)dependencyObject.GetValue(BodyProperty);
    }

    public static void SetBody(DependencyObject dependencyObject, string body)
    {
        dependencyObject.SetValue(BodyProperty, body);
    }

    private static void OnBodyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        string newValue = (string)e.NewValue;
        var webBrowser = (WebBrowser)d;
        webBrowser.NavigateToString(newValue);
    }
}

WebBrowser を DependancyProperty にバインドする XAML:

<WebBrowser Grid.Column="2" HorizontalAlignment="Center" src:WebBrowserHelper.Body="{Binding HTMLBody}"  VerticalAlignment="Center" Height="Auto" Width="Auto"  />

タブ コントロールの ItemsSource にバインドされた ViewModel:

public class SomeVM : ViewModelBase, INotifyPropertyChanged
{

    private string _htmlBody;
    private SomeView _myView = new SomeView();

    public SomeVM (string tabName)
    {
        TabName = tabName;
        string contentsAsHTML = do_a_whole_bunch_of_stuff_to_generate_an_HTML_string();
        HTMLBody = contentsAsHTML;
    }

    public string HTMLBody
    {
        get { return _htmlBody; }
        set
        {
            if (_htmlBody != value)
            {
                _htmlBody = value;
                RaisePropertyChanged("HTMLBody");
            }
        }
    }

    public SomeView View
    {
        get {return _myView;}
        set { }
    }

    public string TabName { get; set; }
}

MainViewModel、タブ コレクションの作成:

    private ObservableCollection<SomeVM> _tabs;
    public ObservableCollection<SomeVM> Tabs
    {
        get
        {
            if (_tabs== null)
            {
                _tabs= new ObservableCollection<SomeVM>();
                _tabs.Add(new SomeVM("Tab 1"));
                _tabs.Add(new SomeVM("Tab 2"));
                _tabs.Add(new SomeVM("Tab 3"));
            }
            return _tabs;
        }
    }

タブ バインドを設定する MainWindow.xaml:

           <TabControl ItemsSource="{Binding Tabs, Source={StaticResource vm}}"
                        >
                <TabControl.ItemTemplate>
                    <DataTemplate>
                        <TextBlock
                            Text="{Binding TabName}" />
                    </DataTemplate>
                </TabControl.ItemTemplate>
                <TabControl.ContentTemplate>
                    <DataTemplate>
                        <ContentPresenter Content="{Binding View}" />
                    </DataTemplate>
                </TabControl.ContentTemplate>
           </TabControl>

私の問題は、タブを変更するたびに「OnBodyChanged」が複数回発生することです。HTML の読み込みには数秒かかりますが、viewmodel でプロパティが実際に変更されたときにのみ読み込まれるようにしたいと考えています。

編集

これが私の問題を再現する最小のサンプル プロジェクトです

4

1 に答える 1

1

問題は、アタッチされたプロパティやMVVMとは関係ありません。実際、本当の問題は、選択したタブを変更するたびにTabControlが子を破棄して再作成することです。これは、ハンドラーが複数回呼び出される理由を説明します。VisualTreeには、選択したタブのみが含まれます。

別のコントロールで試すことができる場合は、エラーがないことがわかります。

この問題を解決するために、この投稿にリダイレクトします。

于 2012-10-02T19:44:53.347 に答える