How to unsubscribe from a loaded event in a derived control? - c#

I'm just playing with the grid class, to make it "cleaver". So I want to be able to use it in xaml and just specify how many rows I want, or columns etc, to do this I've got the code below. It all works fine, I used the loaded event to add rows and columns, but now I am thinking how should I unsubscribe from this event? I can't find straight forward information of how to do it?
public class MyFormGrid : Grid
{
public static readonly DependencyProperty ColumnsProperty =
DependencyProperty.Register("Columns", typeof(int), typeof(ASLFormGrid), new PropertyMetadata(0));
public static readonly DependencyProperty RowsProperty =
DependencyProperty.Register("Rows", typeof(int), typeof(ASLFormGrid), new PropertyMetadata(0));
public MyFormGrid()
{
Loaded += MyGrid_Loaded;
}
public int Columns
{
get { return (int)GetValue(ColumnsProperty); }
set { SetValue(ColumnsProperty, value); }
}
public int Rows
{
get { return (int)GetValue(RowsProperty); }
set { SetValue(RowsProperty, value); }
}
private void MyGrid_Loaded(object sender, RoutedEventArgs e)
{
for (var i = 0; i < Columns; i++)
{
ColumnDefinitions.Add(new ColumnDefinition());
}
for (var i = 0; i < Rows; i++)
{
RowDefinitions.Add(new RowDefinition(););
}
}
}
Kind Regards

This could easily be put inside your loaded event handler:
public class MyFormGrid : Grid
{
...
public MyFormGrid()
{
Loaded += MyGrid_Loaded;
}
...
private void MyGrid_Loaded(object sender, RoutedEventArgs e)
{
Loaded -= MyGrid_Loaded;
...
}
}

Related

USer Control Custom event and set get property

I have 2 labels and a property in user control:
Here is property:
private int _SelectIndex;
[Browsable(true)]
public int SelectIndex { get; set; }
and 2 labels:
Label lbl1, lbl2;
void iControl()
{
lbl1 = new Label();
lbl2 = new Label();
lbl1.Name = "lbl1";
lbl2.Name = "lbl2";
lbl1.Click += lbl_Click;
lbl2.Click += lbl_Click;
this.Controls.Add(lbl1);
this.Controls.Add(lbl2);
}
Click:
void lbl_Click(object sender, EventArgs e)
{
Label selectedlbl = sender as Label;
if(selectedlbl.Name == "lbl1")
this.Select = 1;
else
this.Select = 2;
}
Class Event:
public class SelectEventArgs : EventArgs
{
private int index;
public SelectEventArgs(int index)
{
this.index = index;
}
public int ItemIndex
{
get
{
return index;
}
}
}
Custom event in my control:
public event EventHandler SelectEvent;
protected virtual void OnSelectEvent()
{
if (SelectEvent!= null)
SelectEvent(this, new SelectEventArgs(this._SelectIndex));
}
I need an event to get and set property value in MainForm as following:
int index = 0;
public Form1()
{
InitializeComponent();
this.icontrol = new iControl();
this.SelectEvent += Select();
}
void Select(object sender, SelectItem e)
{
//use this to set value of Select
this.icontrol.SelectIndex = index;
//and this to get value of Select
index = this.icontrol.SelectIndex;
}
Select is empty.
How to get it to work?
I post here for any one need it:
1.Declare a delegate:
public delegate void SelectIndexEventHandler(object sender, SelectEventArgs e);
public class SelectEventArgs : EventArgs
{
private int index;
public SelectEventArgs(int index)
{
this.index = index;
}
public int ItemIndex
{
get { return index; }
set { index = value; }
}
}
2. declare an event SelectIndexChanged and a method OnSelectIndexChanged:
public event SelectIndexEventHandler SelectIndexChanged;
protected virtual void OnSelectIndexChanged(SelectEventArgs e)
{
if (SelectIndexChanged != null)
SelectIndexChanged(this, e);
}
3.Call it in setter:
public int SelectIndex
{
get { return _SelectIndex; }
set {
_SelectIndex = value;
OnSelectIndexChanged(new SelectEventArgs(value));
}
}
and then MainForm:
this.gListBox1.SelectIndexChanged += icontrol_SelectIndexChanged;
void icontrol_SelectIndexChanged(object sender, SelectEventArgs e)
{
var current = e.ItemIndex;
}
thank again jbmintjb Reza Aghaei.
The code has multiple issues. Consider these tips to solve the issues:
SelecetEvent does't belong to the Form. The event belongs to icontrol.
this.SelectEvent += Select(); is incorrect, you should use:
icontrol.SelectEvent += Select;
When you have a custom event args, you should define the event this way:
public event EventHandler<SelectEventArgs> SelectEvent;
You should raise the event in setter of your property, using OnSelectEvent method which you created.
To learn more about events take a look at C# Handling and Raising Events.
Take a look at the SelectedIndexChanged event on the listbox control, think that is what you are looking for

DependencyProperty not being attached

SetFocusIndex is called when navigating away from a view. This should register/attach a DependencyProperty to the specified control.
GetFocusIndex is called upon returning to the view. This should extract the registered/attached DependencyProperty which holds the index of the last control (EightTileGrid item etc) that had focus.
I see the correct DependencyProperty being set , but when I retrieve it on back navigation it returns -1 value as if the property was never set.
Setting logic:
public static readonly DependencyProperty FocusIndexProperty =
DependencyProperty.RegisterAttached(
"FocusIndex",
typeof(int),
typeof(GamePadFocusManager),
new PropertyMetadata(-1));
public static int GetFocusIndex(DependencyObject obj)
{
return (int)obj.GetValue(FocusIndexProperty);
}
public static void SetFocusIndex(DependencyObject obj, int value)
{
obj.SetValue(FocusIndexProperty, value);
}
private void OnNavigatingMessage(NavigatingMessage navigatingMessage)
{
Messenger.Default.Unregister<NavigatingMessage>(this, OnNavigatingMessage);
SaveFocusIndex();
}
private void SaveFocusIndex()
{
var controls = VisualTreeQueryHelper.FindChildrenOfType<Control>(this).ToList();
for (int i = 0; i < controls.Count; i++)
{
if (controls[i].ContainsFocus())
{
GamePadFocusManager.SetFocusIndex(this, i);
break;
}
}
}
Retrieving logic:
private void BaseTileGrid_GotFocus(object sender, RoutedEventArgs e)
{
if ((FocusManager.GetFocusedElement() == this) || !this.ContainsFocus())
{
SetFocusOnChildControl();
}
}
public virtual void SetFocusOnChildControl()
{
var focusIndex = Math.Max(0, GamePadFocusManager.GetFocusIndex(this));
var contentControls = VisualTreeQueryHelper.FindChildrenOfType<ContentControl>(this).ToList();
DispatcherHelper.BeginInvokeAtEndOfUiQueue(() =>
{
if (contentControls.Count > focusIndex)
{
if (this.ContainsFocus())
{
GamePadFocusManager.FocusOn(contentControls[focusIndex]);
}
}
});
}
Grid
public class BaseTileGrid : Control
{
...
}
Xaml:
<GridLayout:BaseTileGrid x:Name="recentlyWatched"
Style="{StaticResource FourByTwoGrid}"
ItemsSource="{Binding ItemViewModels}"
ItemTemplate="{StaticResource GridLayoutDataTemplateSelector}"
OverflowPageTitle="{Binding OverflowPageTitle}"
MoreButtonCommand="{Binding MoreButtonCommand}"/>

WPF percentage status shown in label MVVM

I got some problem in showing download percentage in GridView of WCF. I used MVVM pattern.
Here is my background worker in application start:
public partial class MainWindow : Window
{
public MainWindow()
{
Overall.EverythingOk = "Nothing";
InitializeComponent();
//IRepo repo = new Repo();
ViewModel.MainWindowsViewModel viewModel = new ViewModel.MainWindowsViewModel();
this.DataContext = viewModel;
BackGroundThread bgT = new BackGroundThread();
bgT.bgWrk.RunWorkerAsync();
}}
Here is the DoWork function in BackGroundTHread class
public void bw_DoWork(object sender, DoWorkEventArgs e)
{
if (!Overall.stopStatus)
{
for (int i=0; i < 10000; i++)
{
Overall.PercentageDwnd = i;
Overall.caseRefId = "999999";
if (i == 9998)
{
i = 1;
}
}
}
}
Overall.PercentageDwnd and Overall.caseRefId are static variable (you can call from everywhere in the application) and always update until the background worker completed. I got another ViewModel called TestViewModel and here it is.
public class TestViewModel:BindableBase
{
private String _UpdatePer=Overall.PercentageDwnd.ToString();
public String UpdatePercentage
{
get { return _UpdatePer; }
set { SetProperty(ref _UpdatePer, value); }
}
private ObservableCollection _ViewAKA = new ObservableCollection();
private tblTransaction model;
public TestViewModel(tblTransaction model)
{
// TODO: Complete member initialization
}
public ObservableCollection ViewAKA
{
get { return _ViewAKA; }
set { SetProperty(ref _ViewAKA, value); }
}
}
I bind with TestView.xaml file
<Window x:Class="EmployeeManager.View.TestView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="TestView" Height="359.774" Width="542.481">
<Grid Margin="0,0,2,0">
<Label Content="{Binding UpdatePercentage,UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Left" Background="Red" Foreground="White" Margin="130,86,0,0" VerticalAlignment="Top" Width="132" Height="39">
</Label>
</Grid>
</Window>
There is no real time update at Label even though I bind UpdatePercentage to it. How can I update real time to label?
The problem is that you are updating the static properties, which are not bound to anything. You need to update and raise the property changed notification for the properties which are bound to the label controls, i.e. UpdatePercentage
Can you pass the TestViewModel instance into the RunWorkerAsync call?
bgT.bgWrk.RunWorkerAsync(testViewModel);
And then access in the DoWork event handler:
public void bw_DoWork(object sender, DoWorkEventArgs e)
{
if (!Overall.stopStatus)
{
var viewModel = e.Argument as TestViewModel;
for (int i=0; i < 10000; i++)
{
Overall.PercentageDwnd = i;
viewModel.UpdatePercentage = i;
Overall.caseRefId = "999999";
if (i == 9998)
{
i = 1;
}
}
}
}
Here is answer link:
https://social.msdn.microsoft.com/Forums/vstudio/en-US/02a7b9d1-1c26-4aee-a137-5455fee175b9/wpf-percentage-status-shown-in-label-mvvm?forum=wpf
i need to trigger when the Overall.PercentageDwnd property changes.
Edited
In Overall Class:
public class Overall
{
private static int _percentage;
public static int PercentageDwnd
{
get { return _percentage; }
set
{
_percentage = value;
//raise event:
if (PercentageDwndChanged != null)
PercentageDwndChanged(null, EventArgs.Empty);
}
}
public static string caseRefId { get; set; }
public static bool stopStatus { get; set; }
public static event EventHandler PercentageDwndChanged;
}
In TestViewModel:
public class TestViewModel : BindableBase
{
private String _UpdatePer = Overall.PercentageDwnd.ToString();
public String UpdatePercentage
{
get { return _UpdatePer; }
set { SetProperty(ref _UpdatePer, value); }
}
public TestViewModel(tblTransaction model)
{
Overall.PercentageDwndChanged += Overall_PercentageDwndChanged;
// TODO: Complete member initialization
}
private void Overall_PercentageDwndChanged(object sender, EventArgs e)
{
this.UpdatePercentage = Overall.PercentageDwnd.ToString();
}
}
Since you have bound the TextBlock in the view to the UpdatePercentage source property, you need to set this one and raise the PropertyChanged event whenever you want to update the Label in the view. This means that you need to know when the Overall.PercentageDwnd property changes.
Credit to
Magnus (MM8)
(MCC, Partner, MVP)
Thanks All

ICollectionView's CurrentChanged event not working if we create full property

when we create auto-property of ICollectionView then CurrentChanged event is working properly after refreshing Employee collection.
public ICollectionView EmployeeCollectionView{get; set; }
public EmployeeMasterViewModel(IEmployeeMasterView view, IUnityContainer container)
{
GetEmployee();
EmployeeCollectionView.CurrentChanged += new EventHandler(EmployeeCollectionView_CurrentChanged);
}
And when we create full-property then CurrentChanged event is not working.
private ICollectionView _employeeCollectionView;
public ICollectionView EmployeeCollectionView
{
get { return _employeeCollectionView; }
set { _employeeCollectionView = value; OnPropertyChanged("EmployeeCollectionView");}
}
public EmployeeMasterViewModel(IEmployeeMasterView view, IUnityContainer container)
{
GetEmployee();
EmployeeCollectionView.CurrentChanged += new EventHandler(EmployeeCollectionView_CurrentChanged);
}
void EmployeeCollectionView_CurrentChanged(object sender, EventArgs e)
{
var currentEmployee = EmployeeCollectionView.CurrentItem as EmployeeMaster;
}
please suggest if i missing something.
Have you bind EmployeeCollectionView_CurrentChanged event after refreshing employee collection? because if you refreshing employee collection then EmployeeCollectionView_CurrentChanged connection has been lost.
like-
private void Refresh()
{
GetEmployee();
EmployeeCollectionView.CurrentChanged += new EventHandler(EmployeeCollectionView_CurrentChanged);
}
If you expect EmployeeCollectionView to change (which seems so, otherwise you would not need an OnPropertyChanged, I'd recommend to add the Events in the setter of your property like following:
private ICollectionView _employeeCollectionView;
public ICollectionView EmployeeCollectionView
{
get { return _employeeCollectionView; }
set
{
if (_employeeCollectionView != value)
{
if (_employeeCollectionView != null)
{
_employeeCollectionView.CollectionChanged -= EmployeeCollectionView_CurrentChanged;
}
_employeeCollectionView = value;
_employeeCollectionView.CollectionChanged += EmployeeCollectionView_CurrentChanged;
OnPropertyChanged("EmployeeCollectionView");
}
}
}
public EmployeeMasterViewModel(IEmployeeMasterView view, IUnityContainer container)
{
GetEmployee();
}
private void EmployeeCollectionView_CurrentChanged(object sender, EventArgs e)
{
var currentEmployee = EmployeeCollectionView.CurrentItem as EmployeeMaster;
}

Module not rendering

In my application i'm trying to load the main module trough code. Everything works up to the point of rendering and i have NO clue why it isn't rendering. The content has the right values and everything.. My guess is that something went wibbly wobbly and I seem to be missing it.
Control that holds the view
[ContentPropertyAttribute("ContentView")]
public class ContentControlExtened : ContentControl
{
public static readonly DependencyProperty ContentProperty =
DependencyProperty.Register(
"Type",
typeof(Type),
typeof(ContentControl),
new FrameworkPropertyMetadata(null, ContentTypeChanged));
public static readonly DependencyProperty ContentViewProperty =
DependencyProperty.Register(
"View",
typeof(FrameworkElement),
typeof(ContentControl),
new FrameworkPropertyMetadata(null, ContentViewChanged));
private static void ContentViewChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
//throw new NotImplementedException();
}
public ContentControlExtened()
{
this.Loaded += ContentControlLoaded;
}
private void ContentControlLoaded(object sender, RoutedEventArgs e)
{
this.LoadContent();
}
private void LoadContent()
{
UserControl u = null;
if (Type != null)
{
u = (UserControl)ServiceLocator.Current.GetInstance(this.Type);
}
u.Background = new SolidColorBrush(Color.FromRgb(0, 0, 255));
this.View = u;
}
public Type Type
{
get { return (Type)GetValue(ContentProperty); }
set { SetValue(ContentProperty, value); }
}
public FrameworkElement View
{
get { return (FrameworkElement)GetValue(ContentProperty); }
set
{
SetValue(ContentProperty, value);
}
}
}
Method in shell to load the main view of the given moduleInfo
private void OpenMainView(ModuleInfo module)
{
Type moduleType = Type.GetType(module.ModuleType);
var moduleMainViewType = moduleType.Assembly.GetType(moduleType.Namespace + ".Views.MainView");
this.ContentHolder.MainContent.Type = moduleMainViewType;
}
The contructor of the mainview is straight forward. Just standard control InitializeComponent() and Datacontext is being set trough the servicelocator.
public FrameworkElement View
{
get { return (FrameworkElement)GetValue(ContentProperty); }
set
{
SetValue(ContentProperty, value);
}
}
Here you are getting and setting the ContentProperty. It should be ContentViewProperty.

Categories