WPF requires quite a shift of thinking from winforms, I prefer it. I suggest you look up the M-V-VM pattern for WPF. The first thing you need to do is separate yor View model, it makes the code
much cleaner and separates concerns much better. Here is the
ViewModel
base class:
public abstract class ViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
Then a view model for the item (
please note the comments in code!):
public class PageNumber : ViewModel
{
bool m_selected = false;
string m_text;
public string Text
{
get { return m_text; }
set
{
if (m_text == value)
return;
m_text = value;
OnPropertyChanged("Text");
}
}
public bool Selected
{
get { return m_selected; }
set
{
if (m_selected == value)
return;
m_selected = value;
OnPropertyChanged("Selected");
}
}
public PageNumber(string pageNumberArg, bool selected = false)
{
Text = pageNumberArg;
Selected = selected;
}
}
And now code to doing what was mixed up in the Window's class:
public class MyViewModel : ViewModel
{
PageNumber m_currentPage;
ObservableCollection<pagenumber> m_pageCollection = new ObservableCollection<pagenumber>();
public PageNumber CurrentPage
{
get { return m_currentPage; }
set
{
if (m_currentPage == value)
return;
m_currentPage = value;
OnPropertyChanged("CurrentPage");
}
}
public ObservableCollection<pagenumber> PageCollection
{
get { return m_pageCollection; }
set
{
if (m_pageCollection == value)
return;
m_pageCollection = value;
OnPropertyChanged("PageCollection");
}
}
public void Next()
{
int currentIndex = PageCollection.IndexOf(PageCollection.First(x => x.Selected));
PageCollection[currentIndex].Selected = false;
PageCollection[currentIndex + 1].Selected = true;
}
public MyViewModel()
{
PageCollection.Add(new PageNumber(" 0 ", true));
PageCollection.Add(new PageNumber(" 1 "));
PageCollection.Add(new PageNumber(" 2 "));
PageCollection.Add(new PageNumber(" 3 "));
PageCollection.Add(new PageNumber(" 4 "));
PageCollection.Add(new PageNumber(" 5 "));
CurrentPage = PageCollection[0];
}
}</pagenumber></pagenumber></pagenumber>
Now your window code becomes something simple:
public partial class MainWindow : Window
{
public MyViewModel ViewModel
{
get { return DataContext as MyViewModel; }
set { DataContext = value; }
}
public MainWindow()
{
InitializeComponent();
ViewModel = new MyViewModel();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
ViewModel.Next();
}
}
Finally, your Items control XAML (Note the bold part)
<itemscontrol name="pageControl" itemssource="{Binding Path=PageCollection}" grid.row="0">
<itemscontrol.template>
<controltemplate targettype="ItemsControl">
<border>
<stackpanel>
<itemspresenter></itemspresenter>
</stackpanel>
</border>
</controltemplate>
</itemscontrol.template>
<itemscontrol.itemspanel x:uid="pageItemTemplate" xmlns:x="#unknown">
<itemspaneltemplate>
<stackpanel orientation="Horizontal" />
</itemspaneltemplate>
</itemscontrol.itemspanel>
<itemscontrol.itemtemplate>
<datatemplate>
<button x:name="pageNumberButton" margin="3,4" content="{Binding Path=Text}" xmlns:x="#unknown">
<button.style>
<style targettype="{x:Type Button}">
<setter property="Template">
<setter.value>
<controltemplate targettype="Button">
<border cornerradius="2,2,2,2" horizontalalignment="Center" x:name="borderTemplate" background="{TemplateBinding Background}">
<contentpresenter />
</border>
<controltemplate.triggers>
<trigger property="IsMouseOver" value="true">
<setter targetname="borderTemplate" property="Border.BorderBrush" value="Gray" />
<setter targetname="borderTemplate" property="Border.BorderThickness" value="1" />
</trigger>
<trigger property="IsPressed" value="true">
<setter targetname="borderTemplate" property="Border.BorderBrush" value="Lime" />
</trigger>
<trigger property="IsFocused" value="true">
<setter targetname="borderTemplate" property="Border.Background" value="#FD7" />
</trigger>
<trigger property="IsEnabled" value="false">
<setter targetname="borderTemplate" property="Border.Background" value="LightGray"></setter>
</trigger>
</controltemplate.triggers>
</controltemplate>
</setter.value>
</setter>
<style.triggers>
<datatrigger binding="{Binding Path=Selected}" value="true">
<setter property="Background" value="White" />
</datatrigger>
</style.triggers>
</style>
</button.style>
</button>
</datatemplate>
</itemscontrol.itemtemplate>
This uses a data trigger bound to the
Selected
property of the
PageNumber
view model, you could also use a converter to do a similar job. Additionally you can move the styling out to resources if you want to re-use it.
Notice that the there little direct UI stuff in the view model and that binding takes care of pretty much everything on the display side, this is normally the case if you get a WPF app right. I wrote a whole banking app with almost no code in the main window's class, and nearly everything was handled with templates and the M-V-VM pattern.