What I am trying to make: I want to click on a button that lets me name my item. The item is then added to the listview.
So far the only way I can add an item is if I directly name it in the code.
Here is my code so far:
private void button_add(object sender, RoutedEventArgs e)
{
ListViewItem item = new ListViewItem();
item.Content = "randommmmm";
list1.Items.Add(item);
}
Here is a very basic example that should give you the idea.
MainWindow.xaml.cs:
public partial class MainWindow: Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
popup.IsOpen = true;
}
private void txt_PreviewKeyDown(object sender, KeyEventArgs e)
{
if(e.Key == Key.Enter)
{
list1.Items.Add(txt.Text);
txt.Text = string.Empty;
popup.IsOpen = false;
}
}
}
MainWindow.xaml:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication1"
mc:Ignorable="d"
Title="Window6" Height="300" Width="300">
<StackPanel>
<ListView x:Name="list1" />
<Popup x:Name="popup" Width="300" PlacementTarget="{Binding ElementName=btn}">
<Border Background="White" BorderBrush="AliceBlue" BorderThickness="2">
<TextBox x:Name="txt" Margin="10" PreviewKeyDown="txt_PreviewKeyDown" />
</Border>
</Popup>
<Button x:Name="btn" Content="Add" Click="Button_Click" />
</StackPanel>
</Window>
Clicking on the Button displays a Popup with a TextBox and when you press [Enter] the text in the TextBox is added to the ListView.
If you are serious about WPF and XAML I really recommend you to learn the MVVM design pattern but that's another story :)
You can bind a TextBox to a property in your view model.
<TextBox Text="{Binding ItemName}" />
private string itemName;
public string ItemName
{
get { return itemName; }
set
{
if (value == null || value == itemName) return;
itemName = value;
NotifyOnPropertyChanged(nameof(ItemName));
}
}
So you can use ItemName to create your item.
item.Content = ItemName;
Related
Hi I am new for learning WPF MVVM ,please help a basic question ,thx.
I use a for-loop to create a counter ,but View doesn't get the property changed.
I know I should use INotifyPropertyChanged to make view refresh ,but it still cannot work...
Why Codes below doesn't work?
View:
<Window x:Class="WpfApp5.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp5"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.DataContext>
<local:DemoVM/>
</Window.DataContext>
<Grid>
<Button Content="Button" HorizontalAlignment="Left" Margin="321,297,0,0" VerticalAlignment="Top" Height="38" Width="115" Click="Button_Click"/>
<ProgressBar HorizontalAlignment="Left" Height="30" Margin="98,217,0,0" VerticalAlignment="Top" Width="560" Value="{Binding Number, UpdateSourceTrigger=PropertyChanged}"/>
<TextBlock Text="{Binding Number, UpdateSourceTrigger=PropertyChanged}" Margin="696,217,26,119" FontSize="20"/>
</Grid>
</Window>
ViewModel:
class DemoVM:INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
internal void AddNumber()
{
for (int i = 0; i < 100; i++)
{
Number++;
}
}
int _number;
public int Number
{
get { return _number; }
set
{
_number = value;
OnPropertyChanged(nameof(Number));
}
}
}
MainWindow.cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
DemoVM demoVM = new DemoVM();
demoVM.AddNumber();
}
}
}
ViewDesign:
View
It looks like you already have set the binding context of the view to the DemoVM view model, so in your button click, you need not instantiate a new one.
private void Button_Click(object sender, RoutedEventArgs e)
{
((DemoVM)DataContext).AddNumber();
}
I have a MainWindowViewModel and my MainWindow contains a frame to display project pages.
The first page being displayed is a list of recently opened projects(Similar to Microsoft word) which has it's own ViewModel.
There is no problem in loading the list but when I want to send the user-selected item from this list to the MainWindowViewModel I can not use Find-Ancestor to reach the Window DataContext(It looks like the frame has some restrictions).
How can I send the user-selected item to the MainWindowViewModel?
public class RecentlyOpenedFilesViewModel
{
readonly IFileHistoryService _fileHistoryService;
private ObservableCollection<RecentlyOpenedFileInfo> _RecentlyOpenedFilesList;
public ObservableCollection<RecentlyOpenedFileInfo> RecentlyOpenedFilesList
{
get { return _RecentlyOpenedFilesList; }
set { _RecentlyOpenedFilesList = value; RaisePropertyChanged(); }
}
public RecentlyOpenedFilesViewModel( IFileHistoryService fileService):base()
{
_fileHistoryService = fileService;
RecentlyOpenedFilesList=new ObservableCollection<RecentlyOpenedFileInfo>(_fileHistoryService.GetFileHistory());
}
public void RefreshList()
{
RecentlyOpenedFilesList = new ObservableCollection<RecentlyOpenedFileInfo>(_fileHistoryService.GetFileHistory());
}
}
<Page
x:Class="MyProject.Views.V3.Other.RecentlyOpenedFilesPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyProject.Views.V3.Other"
xmlns:vmv3="clr-namespace:MyProject"
Title="RecentlyOpenedFilesPage">
<Page.Resources>
<DataTemplate x:Key="RecentlyOpenedFileInfoTemplate"
>
<Button
Height="70"
Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListView}}, Path=DataContext.OpenProjectFromPathCommand}"
CommandParameter="{Binding}">
<Button.Content>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="70" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="200" />
</Grid.ColumnDefinitions>
<StackPanel
Grid.Row="0"
Grid.Column="0"
VerticalAlignment="Top">
<TextBlock Text="{Binding Name}" />
<TextBlock Text="{Binding Path}" />
</StackPanel>
<TextBlock
Grid.Row="0"
Grid.Column="1"
Margin="50,0,0,0"
VerticalAlignment="Center"
Text="{Binding DateModified}" />
</Grid>
</Button.Content>
</Button>
</DataTemplate>
</Page.Resources>
<Grid>
<ListView
ItemTemplate="{StaticResource RecentlyOpenedFileInfoTemplate}"
ItemsSource="{Binding RecentlyOpenedFilesList}" />
</Grid>
public RecentlyOpenedFilesPage(MainWindowViewModel vm)
{
this.DataContext = vm;
InitializeComponent();
}
Now I have a direct link between MainWindowViewModel and RecentlyOpenedFilesViewModel but I would like to remove this dependency and use another way of connection like(routed commands which I have a problem with)
The MainWindow contains a frame in which the RecentlyOpenedFilesPage is set to its content.
<Window
x:Class="MyProject.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:fw="clr-namespace:SourceChord.FluentWPF;assembly=FluentWPF" >
<Frame Name="frameMain"/></Window>
public class MainWindowViewModel : RecentlyOpenedFilesViewModel, IMainWindowViewModel
{
private void LoadRecentlyOpenedProjects()
{
CurrentView = new RecentlyOpenedFilesPage(this);
}
}
So, here is my suggested solution. It uses the basic idea to propagate the DataContext from the outside into a frame content, as presented in page.DataContext not inherited from parent Frame?
For demonstration purpose, I provide an UI with a button to load the page, a textblock to display the selected result from the list within the page and (ofcourse) the frame that holds the page.
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid Name="parentGrid">
<TextBlock VerticalAlignment="Top" HorizontalAlignment="Right" Margin="5" Text="{Binding SelectedFile}" Width="150" Background="Yellow"/>
<Button VerticalAlignment="Top" HorizontalAlignment="Left" Margin="5" Click="Button_Click" Width="150">Recent Files List</Button>
<Frame Name="frameMain" Margin="5 50 5 5"
LoadCompleted="frame_LoadCompleted"
DataContextChanged="frame_DataContextChanged"/>
</Grid>
</Window>
Viewmodel classes:
public class BaseVm : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName]string propName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
}
}
public class MyWindowVm : BaseVm
{
private string _selectedFile;
public string SelectedFile
{
get => _selectedFile;
set
{
_selectedFile = value;
OnPropertyChanged();
}
}
}
public class MyPageVm : BaseVm
{
public ObservableCollection<MyRecentFile> Files { get; } = new ObservableCollection<MyRecentFile>();
}
public class MyRecentFile
{
public string Filename { get; set; }
public string FilePath { get; set; }
}
Main code behind:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
parentGrid.DataContext = new MyWindowVm();
}
// Load Page on some event
private void Button_Click(object sender, RoutedEventArgs e)
{
frameMain.Content = new RecentlyOpenedFilesPage(new MyPageVm
{
Files =
{
new MyRecentFile { Filename = "Test1.txt", FilePath = "FullPath/Test1.txt"},
new MyRecentFile { Filename = "Test2.txt", FilePath = "FullPath/Test2.txt"}
}
});
}
// DataContext to Frame Content propagation
private void frame_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
UpdateFrameDataContext(sender as Frame);
}
private void frame_LoadCompleted(object sender, NavigationEventArgs e)
{
UpdateFrameDataContext(sender as Frame);
}
private void UpdateFrameDataContext(Frame frame)
{
var content = frame.Content as FrameworkElement;
if (content == null)
return;
content.DataContext = frame.DataContext;
}
}
Now, the page.xaml ... notice: we will set the page viewmodel to the pageRoot.DataContext, not to the page itself. Instead we expect the page datacontext to be handled from the outside (as we do in the MainWindow) and we can reference it with the page internal name _self:
<Page x:Class="WpfApplication1.RecentlyOpenedFilesPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
Title="RecentlyOpenedFilesPage"
Name="_self">
<Grid Name="pageRoot">
<ListView ItemsSource="{Binding Files}"
SelectedValue="{Binding DataContext.SelectedFile,ElementName=_self}"
SelectedValuePath="FilePath"
DisplayMemberPath="Filename"/>
</Grid>
</Page>
Page code behind to wire up the viewmodel:
public partial class RecentlyOpenedFilesPage : Page
{
public RecentlyOpenedFilesPage(MyPageVm myPageVm)
{
InitializeComponent();
pageRoot.DataContext = myPageVm;
}
}
As you can see, with this setup, no viewmodel knows about any involved view. The page doesn't handle the MainViewmodel, but the page requires a DataContext with a SelectedFile property to be provided from the outside.
The MainViewmodel doesn't know about the recent file list, but allows to set a selected file, no matter where it originates from.
The decision, to initialize the RecentlyOpenedFilesPage with a pre-created viewmodel is not important. You could just as well use internal logic to initialize the page with recent files, then the Mainwindow would not be involved.
Sorry if I replicate, but I'm having a hard time wording this for a decent query.
I'm trying to filter a set of complex objects through an ICollectionView and then display each object that made it through, represented by one of their properties. In this particular example, the collection is a list of ComplexClass objects, each of which containing a Name and Number property. I wish to represent each in a ListBox, sitting within a Popup, by their Name.
Here's the XAML code for the MainWindow:
<Window
x:Name="mainWindow"
x:Class="TestWPF.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:test="clr-namespace:TestWPF"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
</Window.Resources>
<Grid x:Name="mainGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<StackPanel x:Name="buttonStack">
<Button x:Name="popupButton" Click="popupButton_Click" Content="Pop-up!" VerticalAlignment="Top"/>
<Button x:Name="randomInsertButton" Click="randomInsertButton_Click" Content="Random Addition!"/>
</StackPanel>
<Popup x:Name="testPopup" PlacementTarget="{Binding ElementName=popupButton}" PopupAnimation="Scroll" Placement="Left"
AllowsTransparency="True" Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Top">
<Grid>
<Button x:Name="popupsButton" Content="Button" Width="75" HorizontalAlignment="Left" VerticalAlignment="Top"/>
<ListBox x:Name="testListBox" Height="100" DataContext="{Binding ElementName=mainWindow}" ItemsSource="{Binding Source=strings}" ScrollViewer.VerticalScrollBarVisibility="Visible" SelectionChanged="testListBox_Selected"/>
</Grid>
</Popup>
</Grid>
</Window>
The MainWindow's code-behind:
namespace TestWPF
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
static List<ComplexClass> stringList = new List<ComplexClass>();
public ObservableCollection<ComplexClass> strings;
public MainWindow()
{
InitializeComponent();
stringList.Add(new ComplexClass("apple",0));
stringList.Add(new ComplexClass("bat",2));
stringList.Add(new ComplexClass("cattle",6));
stringList.Add(new ComplexClass("dogma",5));
strings = new ObservableCollection<ComplexClass>(stringList);
Binding binding = new Binding();
binding.Source = strings;
testListBox.SetBinding(ListBox.ItemsSourceProperty, binding);
}
private void popupButton_Click(object sender, RoutedEventArgs e)
{
ICollectionView view = CollectionViewSource.GetDefaultView(strings);
view.Filter =
//null;
(o) =>
{
return (o as ComplexClass).Name!=string.Empty;
};
view.SortDescriptions.Add(new SortDescription("Name", ListSortDirection.Descending));
testPopup.IsOpen = !testPopup.IsOpen;
}
private void randomInsertButton_Click(object sender, RoutedEventArgs e)
{
Random r = new Random();
stringList.Add(stringList[r.Next(0, stringList.Count)]);
strings.Add(stringList.Last());
}
private void testListBox_Selected(object sender, RoutedEventArgs e)
{
ComplexClass selected =(ComplexClass)(sender as ListBox).SelectedItem;
stringList.Add(selected);
strings.Add(selected);
}
}
}
And finally, the ComplexClass code:
namespace TestWPF
{
public class ComplexClass
{
public string Name { get; private set; }
public int Number { get; private set; }
public ComplexClass(string name, int number)
{
Name = name;
Number = number;
}
}
}
What it's currently doing is displaying each of the objects as if they've been ToString()-ed: "TestWPF.ComplexClass".
I actually want them to be displayed as:
dogma
cat
bat
apple
in that order.
Can I get some help with this?
A couple of issues here.
First, you are binding to the list in your XAML:
<ListBox ... ItemsSource="{Binding Source=strings}" ... />
but then also setting the binding in code:
Binding binding = new Binding();
binding.Source = strings;
testListBox.SetBinding(ListBox.ItemsSourceProperty, binding);
You need to do one or the other: I'd suggest binding in XAML, and removing the binding stuff from the code-behind.
Second, the ComplexClass items are being ToString-ified because that's the default behaviour of a ListBoxItem when supplied with content (the items in a WPF ListBox are wrapped inside ListBoxItem elements). The easiest way for you to fix this is to set the DisplayMemberPath property on the ListBox:
<ListBox ... ItemsSource="{Binding Source=strings}" DisplayMemberPath="Name" ... />
I have a simple UserControl that I want to display in my stackpanel programmatically
.
When I do, the UC does not show on the screen. If I drag a single instance from the toolbox it works fine.
The User Control is XAML is
<UserControl x:Class="MYProj.Controls.SpecialNumberOption"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="200">
<Viewbox>
<Grid x:Name="LayoutRoot" Background="White" Width="200" Height="300">
<Button x:Name="buttonMe" Content="Button" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="180" Height="150" Style="{StaticResource NumberButtonStyle}" Click="buttonMe_Click"/>
<TextBlock x:Name="subText" HorizontalAlignment="Left" Margin="10,165,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Height="125" Width="180" FontStyle="Italic" TextAlignment="Center"/>
</Grid>
</Viewbox>
</UserControl>
The Codebehind
public partial class SpecialNumberOption : UserControl
{
public event RoutedEventHandler Click;
public SpecialNumberOption()
{
InitializeComponent();
this.applyStyle();
}
public SpecialNumberOption(SurveyQuestionOption option)
{
this.buttonMe.Content = option.Text;
this.subText.Text = option.SubText;
this.applyStyle();
}
private void applyStyle()
{
this.buttonMe.FontSize = 26;
this.buttonMe.Background = standardBackground;
this.buttonMe.Foreground = standardForecolor;
}
///Raise the event to the outside
private void buttonMe_Click(object sender, RoutedEventArgs e)
{
Click(this, e);
}
}
Implementation
This is how Im adding the control
foreach (var y in x.Options)
{
//Create new instance from An object
var r = new SpecialNumberOption(y);
// Set visibility
r.Visibility = System.Windows.Visibility.Visible;
r.IsEnabled = false;
//Assign the event handler
r.Click += r_Click;
//This is my stackpanel
listOptions.Children.Add(r);
....
}
//Handle the click event
void r_Click(object sender, RoutedEventArgs e)
{
SpecialNumberOption o = (SpecialNumberOption)e.OriginalSource;
....
}
Update
I found when I use the alternate Constructor this is when it ceases to work.
I have to use the default constructor. Is this normal?
I have not checked all of your posted code for correctness but here is the issue with your constructors: you must call InitializeComponent (and it must happen before you access any named elements)
here is a version with a fix:
public SpecialNumberOption()
{
InitializeComponent();
this.applyStyle();
}
public SpecialNumberOption(SurveyQuestionOption option) : this () //will call the empty default constructor
{
this.buttonMe.Content = option.Text;
this.subText.Text = option.SubText;
}
Remark: I consider it bad style for controls to have more than the empty default constructor.
The parameters should be set via a property setter. It enable you and whoever will be reusing your control to use and parameterize it in xaml.
I am having a problem in my project. This is my Solution Explorer:
BLA is an example UserControl that is loaded twice into a MainWindow Grid:
<Window x:Class="UserControlWechseln.MainWindow"
xmlns:local="clr-namespace:UserControlWechseln"
Title="MainWindow" Height="428" Width="1195" xmlns:am="http://schemas.amcharts.com/charts/wpf/2009/xaml">
<Grid Height="1000" Width="1000">
<Grid Height="500" HorizontalAlignment="Left" Margin="12,31,0,0" Name="grid1" VerticalAlignment="Top" Width="142">
<local:BLA Margin="-3,-17,-270,17" />
</Grid>
<Grid Height="500" HorizontalAlignment="Right" Margin="0,6,31,0" Name="grid2" VerticalAlignment="Top" Width="402">
<local:BLA />
</Grid>
</Grid>
</Window>
The XAML Code for the BLA UserControl looks like this:
<UserControl x:Class="UserControlWechseln.BLA"
d:DesignHeight="300" d:DesignWidth="300">
<Grid Name="Bla">
<Button Content="House" Height="23" HorizontalAlignment="Left" Margin="64,237,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="ButtonClick" />
<Button Content="Soccer" Height="23" HorizontalAlignment="Left" Margin="169,237,0,0" Name="button2" VerticalAlignment="Top" Width="75" Click="ButtonClick" />
</Grid>
</UserControl>
And the C# Code for the BLA UserControl looks like this:
public partial class BLA : UserControl {
public BLA() {
InitializeComponent();
}
private void ButtonClick(object sender, RoutedEventArgs e) {
Button btn = sender as Button;
Bla.Children.Clear();
if (btn.Content.ToString() == "House") {
Haus uc1 = new Haus();
Bla.Children.Add(uc1);
} else if (btn.Content.ToString() == "Soccer") {
Fussball uc2 = new Fussball();
Bla.Children.Add(uc2);
}
}
private void Window_Loaded(object sender, RoutedEventArgs e) {
}
private void button1_Click(object sender, RoutedEventArgs e) {
}
private void button1_Click_1(object sender, RoutedEventArgs e) {
}
private void button1_Click_2(object sender, RoutedEventArgs e) {
}
private void button2_Click(object sender, RoutedEventArgs e) {
}
}
}
The problem now is that you get this view:
Is it possible to trigger the Home Button once and the Img in displays on both UserControls "BLA"? They obviously are the same UserControl.
Thanks for your help.
They are different instances of your UserControl, they do not know that the other exists. You are going to need to create Properties and Events. I am sure there is probably a better way of it but here is something I threw together to demonstrate( I also renamed some of your classes because I do not have the same Namespaces that you have). Also you are clearing all of the controls out of your UserControl when you change your image.
Edit added complete example
UserControl
namespace WpfApplication1{
/// <summary>
/// Interaction logic for Bla.xaml
/// </summary>
public partial class Bla : UserControl
{
public event RoutedEventHandler changeHaus
{
add { AddHandler(myEvents.changeHausEvent, value); }
remove { RemoveHandler(myEvents.changeHausEvent, value); }
}
public event RoutedEventHandler changeSoccer
{
add { AddHandler(myEvents.changeSoccerEvent, value); }
remove { RemoveHandler(myEvents.changeSoccerEvent, value); }
}
public Bla()
{
InitializeComponent();
}
private void ButtonClick(object sender, RoutedEventArgs e) {
Button btn = sender as Button;
if (btn.Content.ToString() == "House")
{
SetHaus();
RoutedEventArgs ea = new RoutedEventArgs(myEvents.changeHausEvent);
RaiseEvent(ea);
}
else if (btn.Content.ToString() == "Soccer")
{
SetSoccer();
RoutedEventArgs ea = new RoutedEventArgs(myEvents.changeSoccerEvent);
RaiseEvent(ea);
}
}
public void SetHaus()
{
display.Fill = new SolidColorBrush(Colors.Blue);
}
public void SetSoccer()
{
display.Fill = new SolidColorBrush(Colors.Red);
}
}
public static class myEvents
{
public static RoutedEvent changeHausEvent = EventManager.RegisterRoutedEvent("changeHaus",RoutingStrategy.Tunnel,typeof(RoutedEventHandler), typeof(Bla));
public static RoutedEvent changeSoccerEvent = EventManager.RegisterRoutedEvent("changeSoccer", RoutingStrategy.Tunnel, typeof(RoutedEventHandler), typeof(Bla));
}
}
UserControl Xaml
<UserControl x:Class="WpfApplication1.Bla"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<Grid Name="bla">
<Grid.RowDefinitions>
<RowDefinition Height="3*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Rectangle Name="display" Height="223" Grid.Row="0" />
<Button Grid.Row="1" Content="House" Height="23" HorizontalAlignment="Left" Margin="64,25,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="ButtonClick" />
<Button Grid.Row="1" Content="Soccer" Height="23" HorizontalAlignment="Left" Margin="169,25,0,0" Name="button2" VerticalAlignment="Top" Width="75" Click="ButtonClick" />
</Grid>
</UserControl>
Main Window
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void bla1_changeHaus(object sender, RoutedEventArgs e)
{
bla2.SetHaus();
}
private void bla1_changeSoccer(object sender, RoutedEventArgs e)
{
bla2.SetSoccer();
}
private void bla2_changeHaus(object sender, RoutedEventArgs e)
{
bla1.SetHaus();
}
private void bla2_changeSoccer(object sender, RoutedEventArgs e)
{
bla1.SetSoccer();
}
}
}
MainWindow Xaml
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" xmlns:my="clr-namespace:WpfApplication1">
<Grid>
<my:Bla HorizontalAlignment="Left" Margin="0,12,0,0" x:Name="bla1" VerticalAlignment="Top" changeHaus="bla1_changeHaus" changeSoccer="bla1_changeSoccer" />
<my:Bla HorizontalAlignment="Left" Margin="247,12,0,0" x:Name="bla2" VerticalAlignment="Top" changeHaus="bla2_changeHaus" changeSoccer="bla2_changeSoccer" />
</Grid>
</Window>