The road to C# master trapemiya

C#を中心に、.NETの話題を取り上げます。

ホーム 連絡をする 同期する ( RSS 2.0 ) Login
投稿数  256  : 記事  1  : コメント  10249  : トラックバック  30

ニュース

Since 2005年10月26日

わんくま同盟

わんくま同盟

Microsoft MVP


Visual Developer - Visual C#

記事カテゴリ

書庫

日記カテゴリ

以下で、ユーザーコントロールのViewModelへどのようにアクセスすれば良いのかということを考えていました。

最近MVVMが面白い
http://blogs.wankuma.com/unyora/archive/2009/06/10/174828.aspx

考え方がある程度まとまったので、整理の意味も込めて以下に書いてみます。

MVVMのパターンを見ていると、ViewとViewModelをXamlだけで結び付けているケースがよくあります。これはこれでWPFの優れた仕組みだと思うのですが、実際にアプリケーションを組む場合、これだと疎すぎて扱いにくい場合が多々あります。
例えば伝票画面に伝票ユーザーコントロールを配置した場合を考えてみます。
伝票画面がPaymentSlipWindow、伝票ユーザーコントロールがPaymentSlipです。
それぞれのViewModelをPaymentSlipWindowViewModel、PaymentSlipViewModelとします。

以下に、PaymentSlipのDataContextに、XamlによってPaymentSlipViewModelをセットしている例を示します。

▼PaymentSlip

<UserControl x:Class="WPFPaymentSlipTest.View.PaymentSlip"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="300" Width="300" Background="AliceBlue"
    xmlns:local="clr-namespace:WPFPaymentSlipTest.ViewModel"    
    xmlns:local2="clr-namespace:WPFPaymentSlipTest.View"
    DataContext="{DynamicResource PaymentSlipViewModelKey}">
        ・
        ・
        ・


▼リソース

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:viewModel="clr-namespace:WPFPaymentSlipTest.ViewModel"                
    xmlns:view="clr-namespace:WPFPaymentSlipTest.View"                
                    >

    <viewModel:PaymentSlipViewModel x:Key="PaymentSlipViewModelKey" />

</ResourceDictionary>


▼PaymentSlipWindow

<UserControl x:Class="WPFPaymentSlipTest.View.PaymentSlipWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WPFPaymentSlipTest.View"
    xmlns:model="clr-namespace:WPFPaymentSlipTest.ViewModel" 
             Height="500" Width="376">

    <Grid ShowGridLines="True">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" MinHeight="300" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <local:PaymentSlip Grid.Row="0" x:Name="PaymentSlip" />
        <Button Grid.Row="1" Height="23" Margin="133,12,0,0" Name="bttn_update"
                   VerticalAlignment="Top" HorizontalAlignment="Left" Width="72"
                   Command="{Binding Path=UpdCommand}">更新</Button>
    
    </Grid>
    
</UserControl>

この状態で、更新ボタンを押してUpdCommandを呼びます。UpdCommandでは、PaymentSlipViewModelが持っているUpdateメソッドを呼んで、伝票データを更新したいのです。
ところが、UpdCommandが定義してあるPaymentSlipWindowViewModelからPaymentSlipViewModelのインスタンスを取得することができませんので、Updateメソッドを呼ぶことができません。なぜなら、PaymentSlipとPaymentSlipViewModelはPaymentSlipWindowのXamlで結びつけられており、PaymentSlipWindowViewModelはそれを一切知ることができないからです。
この場合、PaymentSlipWindowのLoadedイベントでPaymentSlipWindowViewModelに自分のインスタンスを渡すという解決策も考えられます。このようにすれば、PaymentSlipWindowViewModelからPaymentSlipWindowのインスタンスが得られ、そこからPaymentSlipのDataContext経由でPaymentSlipViewModelのインスタンスを得ることができるからです。

しかし、この場合はPaymentSlipのDataContextに、PaymentSlipWindowViewModelからコードでPaymentSlipViewModelをセットしてあげるとスムーズに行きます。このようにしておくと、PaymentSlipWindowViewModelはPaymentSlipViewModeを把握していますので、簡単にPaymentSlipViewModelのUpdateメソッドを呼ぶことができます。

 

▼PaymentSlipWindow

<UserControl x:Class="WPFPaymentSlipTest.View.PaymentSlipWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WPFPaymentSlipTest.View"
    xmlns:model="clr-namespace:WPFPaymentSlipTest.ViewModel"
             Height="500" Width="376">

    <Grid ShowGridLines="True">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" MinHeight="300" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <local:PaymentSlip Grid.Row="0" x:Name="PaymentSlip" DataContext="{Binding Path=PaymentSlips}" />
        <Button Grid.Row="1" Height="23" Margin="133,12,0,0" Name="bttn_update"
                                     VerticalAlignment="Top" HorizontalAlignment="Left" Width="72"
                                     Command="{Binding Path=UpdCommand}">更新</Button>
    
    </Grid>
</UserControl>


▼PaymentSlipWindowViewModel

    class PaymentSlipWindowViewModel : ViewModelBase
    {
        private PaymentSlipViewModel _paymentSlips;

        public PaymentSlipViewModel PaymentSlips
        {
            get
            {
                if (_paymentSlips == null)
                    _paymentSlips = new PaymentSlipViewModel();

                return _paymentSlips;
            }
        }
        ・
        ・
        ・

以上をまとめると、MVVMパターンでViewとViewModelをどう結び付けるかは自由ですが、XAMLだけで結び付けてしまうと疎結合が強すぎて、コードから扱いにくくなるということです。もちろん、DataTemplateによるViewとViewModelの結び付けなど、XAMLだけで結び付けると大変便利な場合もありますが、これがMVVMパターンの十分条件では無いということです。

そのことにようやく気がつきました。

投稿日時 : 2009年6月15日 17:38

コメント

# re: 【WPF】 MVVMパターン。ViewとViewModelをXAMLだけで結び付けると疎結合が強すぎて使いづらい場合がある。 2009/06/15 21:58 えムナウ
ViewModel自体は階層構造を持てます。
PaymentSlipWindowViewModel が PaymentSlipViewModel を持つようにです。

このサイトの説明でもそうです。
場合によっては ViewModel のコレクションを持つこともします。
List形式の表もそうですし、MDIっぽいワークスペースとして管理する場合もそうです。
ユーザーコントロールを使うときはユーザーコントロール用のViewModel とメインウィンドウの ViewModel を持ってクローズ可能なワークスペースという形で親が子を管理します。
http://msdn.microsoft.com/ja-jp/magazine/dd419663.aspx

# re: 【WPF】 MVVMパターン。ViewとViewModelをXAMLだけで結び付けると疎結合が強すぎて使いづらい場合がある。 2009/06/16 0:44 trapemiya
>ユーザーコントロールを使うときはユーザーコントロール用のViewModel とメインウィンドウの ViewModel を持ってクローズ可能なワークスペースという形で親が子を管理します。

最初に考えることはXAML中心ではなく、ViewModelをコントロールすることを中心に考えれば良いということなんですね。そして、ViewModelとViewとの結び付けをコードでやるのかXAMLでやるのかはその次に考えれば良い話なんですね。私は最初にViewModelとViewとの結び付けをとにかくXAMLでやることから始めたために壁にぶつかったようです。
だって、
http://msdn.microsoft.com/ja-jp/magazine/dd419663.aspx
に書かれているDataTemplateを使ったViewModelとViewとの結び付きに深く感動したものですから(^^
このことについてもう少し言えば、上記のMSDNのサンプルでは
MainWindowのxamlで、

<HeaderedContentControl
Content="{Binding Path=Workspaces}"
ContentTemplate="{StaticResource WorkspacesTemplate}"
Header="Workspaces"
Style="{StaticResource MainHCCStyle}"
/>

と書かれており、
WorkspacesTemplateはMainWindowResources.xamlに次のように書かれています。

<DataTemplate x:Key="WorkspacesTemplate">
<TabControl
IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding}"
ItemTemplate="{StaticResource ClosableTabItemTemplate}"
Margin="4"
/>
</DataTemplate>

私が例に出したPaymentSlipWindowとPaymentSlipの関係は、MainWindowとHeaderedContentControlの関係なのに、TabControlとWorkspacesの関係のように考えてしまったのが失敗でした。
単なる私の力の無さでしたか・・・orz

# re: 【WPF】 MVVMパターン。ViewとViewModelをXAMLだけで結び付けると疎結合が強すぎて使いづらい場合がある。 2009/06/16 1:26 倉田 有大
サンプルコードの偉大さと、MVVMの入門の難しさがわかりますね。

私はGUIのユーザーコントロールの階層≒ViewModelの階層
みたいなイメージで今のところ組めています。
複雑になるとどうなることやら・・

# re: 【WPF】 MVVMパターン。ViewとViewModelをXAMLだけで結び付けると疎結合が強すぎて使いづらい場合がある。 2009/06/16 12:02 trapemiya
>私はGUIのユーザーコントロールの階層≒ViewModelの階層

基本、そのように考えれば良い気がしています。私もこれで開発を進めていこうと思います。ホントにフロンティアっぽいなぁ・・・。あんまり先陣を切る人じゃないんだけど、業務として開発しなければならないんでorz  いや、ラッキー、ラッキー! うん・・・

# 【WPF】ViewからViewModelへViewのインスタンスを渡す(CommandParameter経由編) 2009/08/10 17:54 The road to C# master trapemiya
【WPF】ViewからViewModelへViewのインスタンスを渡す(CommandParameter経由編)

# re: Ruby で数値を 0 埋めする 2019/01/24 14:09 zzyytt
http://www.fakerolex.us.com
http://www.adidasgazelle.us.com
http://www.goldengooseoutlet.us
http://www.jordanssneakers.us.com
http://www.caterpillarboots.us.com
http://www.nikereact.org


# re: ?WPF? MVVM?????View?ViewModel?XAML???????????????????????????? 2021/08/08 9:49 where to get hydroxychloroquine
premature babies wikipedia https://chloroquineorigin.com/# hydroxychloroquine side effects heart

# generic for doxycycline https://doxycyline1st.com/
buy doxycycline hyclate 100mg without a rx 2022/02/26 17:51 Jusidkid
generic for doxycycline https://doxycyline1st.com/
buy doxycycline hyclate 100mg without a rx

# ed pill https://ed-pills.xyz/
buy ed pills 2022/09/16 14:51 EdPills
ed pill https://ed-pills.xyz/
buy ed pills

# ed meds online https://ed-pills.xyz/
erection pills online 2022/09/17 15:01 EdPills
ed meds online https://ed-pills.xyz/
erection pills online

# prednisone 10mg online https://prednisonepills.site/
prednisone 20mg for sale 2022/11/30 7:55 Prednisone
prednisone 10mg online https://prednisonepills.site/
prednisone 20mg for sale

# Comprehensive side effect and adverse reaction information. Long-Term Effects.
https://edonlinefast.com
Generic Name. Everything what you want to know about pills. 2023/02/17 12:20 EdOnline
Comprehensive side effect and adverse reaction information. Long-Term Effects.
https://edonlinefast.com
Generic Name. Everything what you want to know about pills.

# ï»¿Medicament prescribing information. Actual trends of drug.
https://edonlinefast.com
Get information now. Read here. 2023/02/17 23:07 EdPills
Medicament prescribing information. Actual trends of drug.
https://edonlinefast.com
Get information now. Read here.

# order cytotec online - https://cytotecsale.pro/# 2023/04/29 6:30 Cytotec
order cytotec online - https://cytotecsale.pro/#

# paxlovid pill https://paxlovid.store/
paxlovid cost without insurance 2023/07/13 17:49 Paxlovid
paxlovid pill https://paxlovid.store/
paxlovid cost without insurance

# gГјnstige online apotheke 2023/09/26 14:15 Williamreomo
https://onlineapotheke.tech/# online apotheke versandkostenfrei
versandapotheke deutschland

# internet apotheke 2023/09/27 1:18 Williamreomo
http://onlineapotheke.tech/# online apotheke versandkostenfrei
versandapotheke

# online apotheke preisvergleich 2023/09/27 2:26 Williamreomo
http://onlineapotheke.tech/# versandapotheke
versandapotheke deutschland

# online apotheke gГјnstig 2023/09/27 3:17 Williamreomo
http://onlineapotheke.tech/# gГ?nstige online apotheke
п»?online apotheke

# п»їonline apotheke 2023/09/27 7:08 Williamreomo
http://onlineapotheke.tech/# versandapotheke
versandapotheke

# online apotheke deutschland 2023/09/27 9:15 Williamreomo
https://onlineapotheke.tech/# online apotheke versandkostenfrei
online apotheke preisvergleich

# comprare farmaci online con ricetta 2023/09/27 16:50 Rickeyrof
acheter sildenafil 100mg sans ordonnance

# п»їonline apotheke 2023/09/27 17:54 Terrywef
acheter sildenafil 100mg sans ordonnance

# canada mail order drug 2023/10/15 4:44 Kiethamert
https://gabapentin.world/# gabapentin generic

# reputable canadian pharmacies online 2023/10/16 15:22 Dannyhealm
Their international health advisories are invaluable. https://mexicanpharmonline.shop/# reputable mexican pharmacies online

# top canadian pharmacies 2023/10/16 22:28 Dannyhealm
They offer the best prices on international brands. https://mexicanpharmonline.shop/# mexican mail order pharmacies

# canada pharmcy 2023/10/17 4:04 Dannyhealm
They maintain a high standard of hygiene and cleanliness. https://mexicanpharmonline.com/# pharmacies in mexico that ship to usa

# mail order canada 2023/10/18 18:51 Dannyhealm
Get information now. http://mexicanpharmonline.shop/# mexican pharmaceuticals online

# mexican rx online 2023/10/19 1:47 Dannyhealm
They have expertise in handling international shipping regulations. http://mexicanpharmonline.shop/# mexican border pharmacies shipping to usa

# doxycycline 200 mg https://doxycycline.forum/ doxycycline pills 2023/11/25 14:39 Doxycycline
doxycycline 200 mg https://doxycycline.forum/ doxycycline pills

# safe canadian internet pharmacies 2023/11/29 14:42 MichaelBum
http://claritin.icu/# buy ventolin inhalers online

# best online canadian pharmacies 2023/11/30 16:04 MichaelBum
http://clomid.club/# can i purchase generic clomid pills

# Sildenafil rezeptfrei in welchem Land 2023/12/16 19:47 StevenNuant
http://apotheke.company/# п»?online apotheke

# best ed pills https://edpills.tech/# men's ed pills 2023/12/23 9:32 EdPills
best ed pills https://edpills.tech/# men's ed pills

Post Feedback

タイトル
名前
Url:
コメント