Monday, August 31, 2009

M-V-VM Product Configuration

Deb and I have created many solutions that support sales or engineering efforts. Each application is a little different, driven by the unique aspects of the product we are selling/designing. We have built systems to sell cars, to quote multi-million dollar communications infrastructure projects, to design chemical plants and gear boxes.

video

You do enough of these applications and you start to see a software design pattern. You also realize just how important the role of the subject matter expert is in helping you create a successful application.


Our first Silverlight product configuration solution is a Cookie Designer. With a lifetime of experience eating cookies and a trip to the store to read the packaging, I now consider myself a subject matter expert. You can test drive the program HERE.

The Cookie Designer is an entry in the Summer Silverlight Coding Competition -- please try it and vote for our solution. Community points are an important part of the judging in this contest.

Our cookie product configuration solution is composed of a set of ingredients that can be combined without any mutually exclusive constraints. Anyone for cinnamon oatmeal dark chocolate chunk?

The secret to creating a convincing picture is to have each ingredient on its own separate layer and to make visible the layers that are involved -- enter the M-V-VM pattern, and in this case used as an adapter / translator between the composition of the model and what is shown.


<Canvas x:Name="CookieRoot" Height="400" HorizontalAlignment="Center" VerticalAlignment="Center" Width="400" Clip="M0,0L400,0 400,400 0,400z" RenderTransformOrigin="0.5,0.5">



<Image Height="381" Width="404" Canvas.Left="-9" Canvas.Top="8" Source="Cookie_Images/Base Cookie.png"/>

<Image x:Name="Cinnamon" Height="382" Width="390" Opacity="0.651" Canvas.Left="6" Canvas.Top="13" Source="Cookie_Images/Cinnamon.png" Visibility="Collapsed">

</Image>

<Image x:Name="PeanutButter" Height="379" Width="385" Opacity="0.478" Canvas.Left="7" Canvas.Top="9" Source="Cookie_Images/Peanut Butter.png" Visibility="Collapsed"/>

<Image x:Name="ReesesPeanutButter" Height="379" Width="385" Opacity="0.478" Canvas.Left="7" Canvas.Top="9" Source="Cookie_Images/Peanut Butter.png" Visibility="Collapsed"/>

<Image x:Name="Cocoa" Height="387" Width="389" Opacity="0.678" Canvas.Left="5" Canvas.Top="5" Source="Cookie_Images/Cocoa.png" Visibility="Collapsed">

</Image>

<Image x:Name="Oatmeal" Height="380" Width="387" Opacity="0.412" Canvas.Left="6" Canvas.Top="7" Source="Cookie_Images/Oatmeal.png" Visibility="Collapsed"/>

<Image x:Name="Peanuts" Height="377" Width="381" Canvas.Left="9" Canvas.Top="10" Source="Cookie_Images/Peanuts.png" Visibility="Collapsed"/>

<Image x:Name="Raisins" Height="373" Width="370" Canvas.Left="15" Canvas.Top="10" Source="Cookie_Images/Raisins.png" Visibility="Collapsed"/>

<Image x:Name="Pecans" Height="313" Width="302" Canvas.Left="56" Canvas.Top="56" Source="Cookie_Images/Pecans.png" Visibility="Collapsed"/>

<Image x:Name="Almonds" Height="286" Width="333" Canvas.Left="14" Canvas.Top="59" Source="Cookie_Images/Almonds.png" Visibility="Collapsed"/>

<Image x:Name="WhiteChocolateChips" Height="351" Width="353" Canvas.Left="18" Canvas.Top="45" Source="Cookie_Images/White Chocolate Chips.png" Visibility="Collapsed"/>

<Image x:Name="SemisweetChocolateChips" Height="400" Width="400" Canvas.Left="0" Canvas.Top="0" Source="Cookie_Images/Dark Chocolate Chips.png" RenderTransformOrigin="0.5,0.5" Visibility="Collapsed">

</Image>

<Image x:Name="MilkChocolateChips" Height="351" Width="380" Canvas.Left="7" Canvas.Top="45" Source="Cookie_Images/Milk Chocolate Chips.png" RenderTransformOrigin="0.5,0.5" Visibility="Collapsed">

</Image>

<Image x:Name="MacadamiaNuts" Height="377" Width="354" Canvas.Left="38" Canvas.Top="12" Source="Cookie_Images/Macadamia Nuts.png" Visibility="Collapsed"/>

<Image x:Name="DarkChocolateChunks" Height="546" Width="456" Canvas.Left="-27" Canvas.Top="-88" Source="Cookie_Images/Dark Chocolate Chunks.png" RenderTransformOrigin="0.5,0.5" Visibility="Collapsed">

</Image>

<Image x:Name="MilkChocolateChunks" Height="546" Width="456" Canvas.Left="-27" Canvas.Top="-88" Source="Cookie_Images/Milk Chocolate Chunks.png" RenderTransformOrigin="0.5,0.5" Visibility="Collapsed">

</Image>

<Image x:Name="WhiteChocolateChunks" Height="546" Width="456" Canvas.Left="-27" Canvas.Top="-88" Source="Cookie_Images/White Chocolate Chunks.png" RenderTransformOrigin="0.5,0.5" Visibility="Collapsed">

</Image>

<Image x:Name="HersheyMiniKisses" Height="134" Width="134" Canvas.Left="134" Canvas.Top="126" Source="Cookie_Images/Hershey Kiss.png" Visibility="Collapsed"/>

</Canvas>





We were careful to name the XAML elements so they could be controlled through an automated binding statement that is generated when the picture is loaded.


void CookieCanvas_Loaded(object sender, RoutedEventArgs e)
{
foreach (Image oItem in CookieRoot.Children)
{
string sName = oItem.Name;
if (string.IsNullOrEmpty(sName))
continue;
var oBinding = new Binding(sName);
oBinding.Mode = BindingMode.OneWay;
oItem.SetBinding(Button.VisibilityProperty, oBinding);
}
}

With all this binding now in place the final step is the view model.

public class CookieVM : ViewModel

{

public CookieVM(Instance oSource)

: base(oSource)

{

}

public override void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)

{

if (e.NewItems.IsNotNull())

foreach (Component oNote in e.NewItems.OfType<Component>())

NotifyPropertyChange(oNote.ClassName);



if (e.OldItems.IsNotNull())

foreach (Component oNote in e.OldItems.OfType<Component>())

NotifyPropertyChange(oNote.ClassName);

}

public Visibility Cinnamon

{

get { return DoesChildOfClassExist("Cinnamon") ? Visibility.Visible : Visibility.Collapsed; }

}

public Visibility PeanutButter

{

get { return DoesChildOfClassExist("PeanutButter") ? Visibility.Visible : Visibility.Collapsed; }

}

public Visibility ReesesPeanutButter

{

get { return DoesChildOfClassExist("ReesesPeanutButter") ? Visibility.Visible : Visibility.Collapsed; }

}

public Visibility Cocoa

{

get { return DoesChildOfClassExist("Cocoa") ? Visibility.Visible : Visibility.Collapsed; }

}

public Visibility Oatmeal

{

get { return DoesChildOfClassExist("Oatmeal") ? Visibility.Visible : Visibility.Collapsed; }

}

public Visibility Peanuts

{

get { return DoesChildOfClassExist("Peanuts") ? Visibility.Visible : Visibility.Collapsed; }

}

public Visibility Raisins

{

get { return DoesChildOfClassExist("Raisins") ? Visibility.Visible : Visibility.Collapsed; }

}

public Visibility HersheyMiniKisses

{

get { return DoesChildOfClassExist("HersheyMiniKisses") ? Visibility.Visible : Visibility.Collapsed; }

}

public Visibility Pecans

{

get { return DoesChildOfClassExist("Pecans") ? Visibility.Visible : Visibility.Collapsed; }

}

public Visibility Almonds

{

get { return DoesChildOfClassExist("Almonds") ? Visibility.Visible : Visibility.Collapsed; }

}

public Visibility DarkChocolateChunks

{

get { return DoesChildOfClassExist("DarkChocolateChunks") ? Visibility.Visible : Visibility.Collapsed; }

}

public Visibility MilkChocolateChunks

{

get { return DoesChildOfClassExist("MilkChocolateChunks") ? Visibility.Visible : Visibility.Collapsed; }

}

public Visibility WhiteChocolateChunks

{

get { return DoesChildOfClassExist("WhiteChocolateChunks") ? Visibility.Visible : Visibility.Collapsed; }

}

public Visibility WhiteChocolateChips

{

get { return DoesChildOfClassExist("WhiteChocolateChips") ? Visibility.Visible : Visibility.Collapsed; }

}

public Visibility SemisweetChocolateChips

{

get { return DoesChildOfClassExist("SemisweetChocolateChips") ? Visibility.Visible : Visibility.Collapsed; }

}

public Visibility MilkChocolateChips

{

get { return DoesChildOfClassExist("MilkChocolateChips") ? Visibility.Visible : Visibility.Collapsed; }

}

public Visibility MacadamiaNuts

{

get { return DoesChildOfClassExist("MacadamiaNuts") ? Visibility.Visible : Visibility.Collapsed; }

}
}

9 comments:

鑽石 said...

很好啊 ..................................................

雪糕 said...

原來這世上能跟你共同領略一個笑話的人竟如此難得........................................

微笑每一天 said...

may the blessing be with you.........................................

志冠少菁伶義 said...

Of two evils choose the least.......................................................

GeraldF_Rotter雅慧 said...

Hello~Nice to meet you~..................................................

Heriberto said...

cool blog,期待更新........................................

PabloDuda0若愛 said...

雖然說上班很累,不過還是得努力應付每一天,看看文章休息一下,謝謝你哦! ..................................................

珮瑜 said...

你的文章給我力量!感謝您!!! ........................................

NealVa憲妤 said...

777成人貼圖區 激情視訊 1069聊天 免費線上a 一葉情交友 av免費看女優 性感卡通美女圖片 成人線上影片觀賞 熟女自拍偷拍 dd 豆豆聊聊天室 性愛愛無碼影片 情趣成人圖片 18禁網站 少女卡通圖 777線上影城 忍者a片 咪咪情色貼圖 色情免費下載影片 一夜情網路交友 a383girl影音 完美女聊天 玩美影音 線上美女 辣妹脫衣 人妻自拍分享 熟女,貼圖 護士 空姐 a圖貼片區 日本女郎寫真集 85cc線上免費影片 微風成人 嘟嘟 777中部人聊天室 性貼圖區 學生性愛援交 情人視訊辣妹 鋼管 免費av線上觀看 洪爺情色電影 大奶. sex無碼影片 免下載色情網站 日本正妹巨乳照片 愛情性遊戲區 後宮電影電影院入口 限制級 成人視訊0204 女人性愛貼片 乳頭走光