I am creating a C# WPF application. I am intending to bind all of the GUI controls via data binding to my ViewModel
, rather than code behind - as per MVVM.
I have made some good headway with this, but unsure about something.
In my ViewModel
, I am binding all the properties like this:
private List<string> listBoxCodec;
public List<string> ListBoxCodec
{
get
{
return this.listBoxCodec;
}
set
{
this.listBoxCodec = value;
OnPropertyChanged("ListBoxCodec");
}
}
and like this:
private string create_FormatSelectedItem;
public string Create_FormatSelectedItem
{
get { return create_FormatSelectedItem; }
set
{
create_FormatSelectedItem = value;
OnPropertyChanged("Create_FormatSelectedItem");
}
}
To my XAML
like this:
<ComboBox x:Name="lstBoxCodec" ItemsSource="{Binding ListBoxCodec}" SelectedItem="{Binding Path=Create_SelectedListBoxCodecsItem, Mode=TwoWay}">
etc...
My GUI has perhaps 50-100 controls/input fields (Text boxes, combo-boxes, etc.) so using the above code to bind these controls is adding up to thousands of lines of code in my ViewModel
.
Is there a more efficient way to bind these controls, or is this pretty much it?
EDIT: Example of the GUI to help with a comment question:
Some example XAML
: (Output)
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.RowSpan="2" Grid.Column="1">
<TextBlock HorizontalAlignment="Left" Margin="18,12,0,0" TextWrapping="Wrap" Text="Summary" VerticalAlignment="Top" FontSize="20" Foreground="#FFED8500" FontFamily="Segoe WP Semibold" FontWeight="Bold"/>
<TextBlock Name="txtJobIntro" HorizontalAlignment="Left" Margin="18,74,0,0" TextWrapping="Wrap" Text="Job information will appear here as you create a new job..." VerticalAlignment="Top" FontWeight="Normal" FontSize="12" Foreground="#FF8E8E8E"/>
<!--Job summary-->
<ScrollViewer Name="CreateSummaryBox" HorizontalAlignment="Stretch" Margin="10,44,0,0" VerticalAlignment="Stretch" Background="#FF505050" Visibility="Collapsed">
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Stretch" TextElement.FontSize="13" TextElement.FontWeight="Normal">
<StackPanel>
<TextBlock HorizontalAlignment="Left" Margin="10,0,10,0" TextWrapping="Wrap" Text="{Binding Heading, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top" FontSize="15" Foreground="#FFDE7900"/>
<TextBlock HorizontalAlignment="Left" Margin="10,5,0,5" TextWrapping="Wrap" Text="{Binding CreateInputFile, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top" FontSize="12" Foreground="#FFD8D8D8"/>
<TextBlock HorizontalAlignment="Left" Margin="10,0,0,0" TextWrapping="Wrap" Text="{Binding Format, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top"/>
<TextBlock HorizontalAlignment="Left" Margin="10,0,0,0" TextWrapping="Wrap" Text="{Binding FormatProfile, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top"/>
<TextBlock HorizontalAlignment="Left" Margin="10,0,0,0" TextWrapping="Wrap" Text="{Binding FPS, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top"/>
<TextBlock HorizontalAlignment="Left" Margin="10,0,0,0" TextWrapping="Wrap" Text="{Binding Res, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top"/>
<TextBlock HorizontalAlignment="Left" Margin="10,0,0,0" TextWrapping="Wrap" Text="{Binding Ratio, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top"/>
<TextBlock HorizontalAlignment="Left" Margin="10,0,0,0" TextWrapping="Wrap" Text="{Binding Duration, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top"/>
<TextBlock HorizontalAlignment="Left" Margin="10,0,0,0" TextWrapping="Wrap" Text="{Binding FileCount, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top"/>
<TextBlock HorizontalAlignment="Left" Margin="10,0,0,0" TextWrapping="Wrap" Text="{Binding A_Type, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top"/>
<TextBlock HorizontalAlignment="Left" Margin="10,0,0,0" TextWrapping="Wrap" Text="{Binding A_Depth, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top"/>
<TextBlock HorizontalAlignment="Left" Margin="10,0,0,0" TextWrapping="Wrap" Text="{Binding A_Samples, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top"/>
<TextBlock HorizontalAlignment="Left" Margin="10,0,0,0" TextWrapping="Wrap" Text="{Binding A_Channels, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top"/>
<TextBlock HorizontalAlignment="Left" Margin="10,0,0,0" TextWrapping="Wrap" Text="{Binding A_ChannelPositions, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top"/>
<!--Effects-->
<TextBlock HorizontalAlignment="Left" Margin="10,10,5,0" TextWrapping="Wrap" Text="Processing Options" VerticalAlignment="Top" FontSize="15" Foreground="#FFDE7900"/>
<TextBlock HorizontalAlignment="Left" Margin="10,0,0,0" TextWrapping="Wrap" Text="{Binding CreateProcessOptions, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top"/>
<!--Output file-->
<TextBlock HorizontalAlignment="Left" Margin="10,10,5,0" TextWrapping="Wrap" Text="Export File" VerticalAlignment="Top" FontSize="15" Foreground="#FFDE7900"/>
<TextBlock HorizontalAlignment="Left" Margin="10,0,0,0" TextWrapping="Wrap" Text="{Binding CreateOutputExportType, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top"/>
<TextBlock HorizontalAlignment="Left" Margin="10,0,0,0" TextWrapping="Wrap" Text="{Binding CreateOutputExportFile, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top"/>
<StackPanel FlowDirection="LeftToRight">
<TextBlock HorizontalAlignment="Left" Margin="10,0,0,0" TextWrapping="Wrap" Text="{Binding CreateOutputVideoFormat, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top"/>
<TextBlock Margin="10,0,0,0" TextWrapping="Wrap" Text="{Binding CreateOutputVideoType, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top"/>
</StackPanel>
<TextBlock HorizontalAlignment="Left" Margin="10,0,0,0" TextWrapping="Wrap" Text="{Binding CreateOutputX, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top"/>
<TextBlock HorizontalAlignment="Left" Margin="10,0,0,0" TextWrapping="Wrap" Text="{Binding CreateOutputFPS, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top"/>
<!--<TextBlock HorizontalAlignment="Left" Margin="10,0,0,0" TextWrapping="Wrap" Text="{Binding CreateOutputScan, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top"/>-->
<TextBlock HorizontalAlignment="Left" Margin="10,0,0,0" TextWrapping="Wrap" Text="{Binding CreateOutputBitDepth, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top"/>
<TextBlock HorizontalAlignment="Left" Margin="10,0,0,0" TextWrapping="Wrap" Text="{Binding CreateOutputAudioType, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top"/>
<TextBlock HorizontalAlignment="Left" Margin="10,0,0,0" TextWrapping="Wrap" Text="{Binding CreateOutputAudioBits, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top"/>
<TextBlock HorizontalAlignment="Left" Margin="10,0,0,0" TextWrapping="Wrap" Text="{Binding CreateOutputAudioChannels, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top"/>
<TextBlock HorizontalAlignment="Left" Margin="10,0,0,0" TextWrapping="Wrap" Text="{Binding CreateOutputAudioRetime, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top"/>
<TextBlock HorizontalAlignment="Left" Margin="10,0,0,0" TextWrapping="Wrap" Text="{Binding CreateOutputExportName, UpdateSourceTrigger=PropertyChanged}" VerticalAlignment="Top"/>
</StackPanel>
</Grid>
</ScrollViewer>
</Grid>
And (User Input)
<Expander Header="Processing" HorizontalAlignment="Stretch" Margin="23,10,0.2,0" VerticalAlignment="Top" FontSize="20" Foreground="#FFED8500" Background="#FF585858" FontWeight="SemiBold" Name="exp2">
<Grid Height="200" HorizontalAlignment="Stretch" TextElement.Foreground="#FFCDCDCD" TextElement.FontSize="13" TextElement.FontFamily="Segoe UI">
<TextBlock HorizontalAlignment="Left" Margin="660,170,-400.2,0" TextWrapping="Wrap" Text="Add upto three processes. List of processes will add to the summary box ->" VerticalAlignment="Top" FontSize="13" Width="457"/>
<TextBlock HorizontalAlignment="Left" Margin="25,9,0,0" TextWrapping="Wrap" Text="Choose Process:" VerticalAlignment="Top" />
<Button Content="Add Process" HorizontalAlignment="Left" Margin="530,168,0,0" VerticalAlignment="Top" Width="113" Command="{Binding Create_AddEffectCommand}" />
<ComboBox ItemsSource="{Binding EffectCategories}" HorizontalAlignment="Left" Margin="23,28,0,0" VerticalAlignment="Top" Width="195" Height="23" Name="CreateChooseEffectCategory" SelectedItem="{Binding EffectCategorySelectedItem}" SelectedIndex="2" SelectedValue="Standards Conversion" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding Create_ShowEffectsCommand}"
CommandParameter="{Binding YourCommandParameter}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</ComboBox>
<TextBlock HorizontalAlignment="Left" Margin="242,9,0,0" TextWrapping="Wrap" Text="Type:" VerticalAlignment="Top" />
<ListBox HorizontalAlignment="Left" Height="113" Margin="242,27,0,0" VerticalAlignment="Top" Width="258" BorderBrush="{x:Null}" FontWeight="SemiBold" Name="CreateLstBoxEffects" ItemsSource="{Binding ListBoxEffects}" SelectedItem="{Binding SelectedListBoxEffectsItem}" IsEnabled="{Binding EffectsListBoxIsEnabled}" />
<Button Content="Preview..." HorizontalAlignment="Left" Margin="25,166,0,0" VerticalAlignment="Top" Width="113" Command="{Binding OpenPreviewCommand}"/>
<TextBlock HorizontalAlignment="Left" Margin="526,8,0,0" TextWrapping="Wrap" Text="Settings:" VerticalAlignment="Top" />
<ComboBox HorizontalAlignment="Left" Margin="526,27,0,0" VerticalAlignment="Top" Width="113" Height="20" x:Name="CreateChooseEffecSetting" SelectedIndex="0">
<ComboBoxItem>Default</ComboBoxItem>
</ComboBox>
</Grid>
</Expander>
List<T>
with MVVM/WPF. You should use something that implementsINotifyCollectionChanged
, likeObservableCollection<T>
. \$\endgroup\$