Accessing Data from a internal class in windows form - c#

I am trying to access the dcam in the internal class. The initialization process starts when it starts.
internal class Ham4MPBase : CameraBase, IDisposable
{
private bool sf;
private Dcam dcam;
public bool Initialize()
{
sf = DcamApi.init();
if (sf)
{
Dcam aDcam = new Dcam();
if (!aDcam.dev_open(0))
{
aDcam = null;
MessageBox.Show("Camera init/open failed");
}
dcam = aDcam;
MessageBox.Show("Camera init/open success");
_initialized = true;
return _initialized;
}
else
{
MessageBox.Show("Camera init failed");
}
}
}
Here, I have data inside of dcam.
Now imagine that I have a button in another namespace where after pressing it would start to acquire image, like below:
public partial class CameraControlPanel : UserControl
{
private Dcam dcam;
private void buttonImageAquire_Click(object sender, EventArgs e)
{
if (dcam == null)
{
MessageBox.Show("Internal Error: dcam is null");
return; // internal error
}
string text = "";
//Start acquisition
m_cap_stopping = false;
dcam.m_capmode = DCAMCAP_START.SEQUENCE; //Continuous Acquisiton
// ....
I am stuck here because dcam shows to be null. How can I expose data from this internal class into my form?

Expose a property to the user control to set the dcam
public partial class CameraControlPanel : UserControl
{
private Dcam mydcam;
public Dcam Camera { get => mydcam; set => mydcam = value; }
}
and then in the form where the control is initialized
public partial class Form1 : Form
{
public Form1()
{
InitializeComponents();
}
protected override OnLoad(EventArgs e)
{
cameraControlPanel1.Camera = ...
}
}

Related

Xamarin Override RemoteControlReceived in Dependency Injection

I am trying to override the RemoteControlRecieved method of the UIApplication and getting the following error:
NSInternalInconsistencyException Reason: There can only be one UIApplication instance.
I understand the issue but have not idea how to solve it. I have a StreamingService class which implements the UIApplication and IStreaming interface. All of my AVPlayer functionality is in this class. the StreamingViewModel class calls the
DependencyService.Get<IStreaming>().Play().
When this line is called I get the above error. I am not sure how to override RemoteControlRecieved from either the StreamingService or the StreamingViewModel class.
any help with code samples is greatly appreciated.
Classes below
public class StreamingViewModel : INotifyPropertyChanged
{
public bool DisplayPlay { get => !isPlaying; }
public bool DisplayPauseStop { get => isPlaying; }
// INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
bool isPlaying;
bool IsPlaying
{
get => isPlaying;
set
{
isPlaying = value;
// Notify the property has changed
OnPropertyChanged("DisplayPlay");
OnPropertyChanged("DisplayPauseStop");
}
}
public void Play()
{
DependencyService.Get<IStreaming>().Play();
IsPlaying = true;
}
public void Pause()
{
DependencyService.Get<IStreaming>().Pause();
IsPlaying = false;
}
public void Stop()
{
DependencyService.Get<IStreaming>().Stop();
IsPlaying = false;
}
}
Class StreamingService
[assembly: Xamarin.Forms.ExportRenderer(typeof(MainPage), typeof(StreamingService))]
[assembly: Dependency(typeof(StreamingService))]
namespace test.iOS
{
public class StreamingService : PageRenderer, IStreaming
{
AVPlayer player;
bool isPrepared;
string dataSource = "https://stream.voxx.pro/radio/8260/radio.mp3";
public override void ViewDidLoad()
{
Console.WriteLine("StreamService ViewDidLoad");
base.ViewDidLoad();
}
public StreamingService()
{
Console.WriteLine("StreamService Default Constructor");
}
public void Play()
{
Console.WriteLine("Play");
if (!isPrepared || player == null)
player = AVPlayer.FromUrl(NSUrl.FromString(dataSource));
//Audio player Notification in lock screen
MPNowPlayingInfo nowPlayingInfo;
nowPlayingInfo = new MPNowPlayingInfo();
nowPlayingInfo.Artist = "Radio Caravan";
nowPlayingInfo.Title = "Join The Caravan";
// Register for receiving controls from lock screen and controlscreen
MPNowPlayingInfoCenter.DefaultCenter.NowPlaying = nowPlayingInfo;
//var command = MPRemoteCommandCenter.Shared;
//command.PlayCommand.Enabled = true;
//command.PauseCommand.Enabled = true;
//command.NextTrackCommand.Enabled = false;
//command.PreviousTrackCommand.Enabled = false;
isPrepared = true;
player.Play();
base.BecomeFirstResponder();
//To listen changes in lock screen
UIApplication.SharedApplication.BeginReceivingRemoteControlEvents();
}
public void Pause()
{
player.Pause();
}
public void Stop()
{
player.Dispose();
isPrepared = false;
}
public override void RemoteControlReceived(UIEvent theEvent)
{
Console.WriteLine("Remote Control Received");
base.RemoteControlReceived(theEvent);
if (theEvent.Subtype == UIEventSubtype.RemoteControlPause)
{
Console.WriteLine("Remote Pause");
player.Pause();
}
else if (theEvent.Subtype == UIEventSubtype.RemoteControlPlay)
{
Console.WriteLine("Remote Play");
player.Play();
}
}
}
}
MainPage.cs
namespace test
{
public partial class MainPage : ContentPage
{
private StreamingViewModel ViewModel { get { return (StreamingViewModel)this.BindingContext; } }
public MainPage()
{
InitializeComponent();
On<Xamarin.Forms.PlatformConfiguration.iOS>().SetUseSafeArea(true);
BindingContext = new StreamingViewModel();
}
// Callbacks to images tapped
private void Play_tapped(object sender, EventArgs e)
{
ViewModel.Play();
}
private void Pause_tapped(object sender, EventArgs e)
{
ViewModel.Pause();
}
private void Stop_tapped(object sender, EventArgs e)
{
ViewModel.Stop();
}
}
}
Interface: IStreaming
public interface IStreaming
{
void Play();
void Pause();
void Stop();
}
NSInternalInconsistencyException Reason: There can only be one UIApplication instance.
You could custom PageRenderer to override RemoteControlReceived method to check whether it works. Because this will use the existing UIApplication.
About isPlaying property, you could use Bindable Properties to define in CustomPage.
About Play/Pause/Stop method, you could use MessagingCenter to send Message from Forms to CustomPageRenderer.
For example, part code of CustomPage as follows:
public partial class CustomPage: ContentPage
{
public CustomPage()
{
InitializeComponent();
}
public static readonly BindableProperty IsPlayingProperty = BindableProperty.Create("IsPlaying", typeof(bool), typeof(CustomPage), null);
public bool IsPlaying
{
get { return (bool)GetValue(IsPlayingProperty); }
set { SetValue(IsPlayingProperty, value); }
}
public void Play()
{
MessagingCenter.Send<object, string>(this, "PlayControl", "Play");
IsPlaying = true;
}
public void Pause()
{
MessagingCenter.Send<object, string>(this, "PlayControl", "Pause");
IsPlaying = false;
}
public void Stop()
{
MessagingCenter.Send<object, string>(this, "PlayControl", "Stop");
IsPlaying = false;
}
}
The part code of CustomPageRenderer as follows:
[assembly: Xamarin.Forms.ExportRenderer(typeof(CustomPage), typeof(CustomPageRenderer))]
namespace XamarinForms20.iOS
{
public class CustomPageRenderer : PageRenderer
{
public override void ViewDidLoad()
{
base.ViewDidLoad();
//...
MessagingCenter.Subscribe<object, string>(this, "PlayControl", (sender, arg) =>
{
if(arg == "Play")
{
//...
}else if (arg == "Pause")
{
//...
}else if (arg == "Stop")
{
//...
}
});
}
public override void RemoteControlReceived(UIEvent theEvent)
{
base.RemoteControlReceived(theEvent);
if (theEvent.Subtype == UIEventSubtype.RemoteControlPlay)
player.Play();
else if (theEvent.Subtype == UIEventSubtype.RemoteControlPause)
player.Pause();
}
}
}
===================================Update================================
You could have a try with adding NSNotificationCenter in ViewDidload method for AVAudioSession.InterruptionNotification.
public override void ViewDidLoad()
...
NSObject _notificationHandle = NSNotificationCenter.DefaultCenter.AddObserver(AVAudioSession.InterruptionNotification, HandleNotification);
...
private void HandleNotification(NSNotification notification)
{
// Do something
NSDictionary userinfo = notification.UserInfo;
NSNumber number = (NSNumber)userinfo.ValueForKey(new NSString("AVAudioSessionInterruptionTypeKey"));
int value = (int)number.NIntValue;
if(value == 1)
{
// pause
}else if(value == 0)
{
// countinue to play
AVAudioSession.SharedInstance().SetActive(true);
}
}

refresh after .showDialog and show items in list - c# .NET

Currently in my program a user opens form 1 to create a new instance of a class and it is then saved to a list. After form 1 closes I would like the main form to reload and show the updated list on the screen. I am having trouble figuring out how to refresh the main navigation and how I would get the list to show on the form.
MainNaviagation
public partial class MainNavigation : Form
{
private Model m_modelObj;
public MainNavigation(Model modelObj)
{
InitializeComponent();
m_modelObj = modelObj;
m_modelObj.ChocolateAdded += m_modelObj_ChocolateAdded;
}
void m_modelObj_ChocolateAdded(Chocolate newChocolate)
{
//whole list of chocolates
List<Chocolate> chocolateList = m_modelObj.ChocolateList;
}
private void button1_Click(object sender, EventArgs e)
{
string candy = comboBox1.SelectedItem.ToString();
Form1 aForm1 = new Form1(textBox1.Text, candy, m_modelObj);
aForm1.ShowDialog();
}
}
Model Class:
{
public delegate void ChocolateAddedEventHander(Chocolate newChocolate);
public class Model
{
public event ChocolateAddedEventHander ChocolateAdded;
public List<Chocolate> ChocolateList = new List<Chocolate>();
public void AddChocolateInList(Chocolate chocolate)
{
ChocolateList.Add(chocolate);
if (ChocolateAdded != null)
ChocolateAdded(chocolate);
}
}
form1
public partial class Form1 : Form
{
Model m_model;
public Form1(string name, string candy, Model modelObj)
{
InitializeComponent();
m_model = modelObj;
string str = name + " selected : ";
label1.Text = str;
}
private void button1_Click(object sender, EventArgs e)
{
Chocolate newChocolate = new Chocolate(comboBoxChocolateSelection.SelectedItem.ToString(), 12.5, true, 2);
m_model.AddChocolateInList(newChocolate);
this.Close();
}
}
chocolates
public class Chocolate
{
#region Fields
public string flavor;
public double cost;
public bool giftWrap;
public int quantity;
#endregion End of Fields
#region Constructors
public Chocolate(string flavor, double cost, bool giftWrap, int quantity)
{
this.flavor = flavor;
this.cost = cost;
this.giftWrap = giftWrap;
this.quantity = quantity;
}
#endregion End of Constructors
}

C# Calling a main form method via other class

I have this project where i contain all my panel instances in my main form.
PanelA aPanelA = new PanelA;
PanelB aPanelB = new PanelB;
This is the form where the program.cs load when it starts.
Because i would like to have a centralize place for each panel calling one another method within them hence i declare them in main. In main, i also make some methods doing certain function in these panel since they are declare in main.
void setPanelA (int iNumber){...}
void setPanelB (string strString){...}
The problem is how would a widget in PanelA call the method setPanelB() via main?
Main.setPanelB("Hello World);
I know i can declare PanelA and PanelB as static. But is this the only way to do it? Because if i declare static to both Panel, i will need to declare some instances within Panel as static too..
I also do not wish to declare PanelA in PanelB or via versa because i could have many type of panels and this would make my code very untidy.
*Edited I had add a sample code here
namespace TestPanel
{
public partial class Form1 : Form
{
PanelA aPanelA = new PanelA();
PanelB aPanelB = new PanelB();
//IT IS POSSIBLE TO HAVE TENS OF DIFFERENT TYPE OF PANEL
public Form1()
{
InitializeComponent();
}
//CENTRAL LOCATION WHERE ALL PANEL COULD CALL EACH OTHER METHOD
public void setPanelACentral(int iNew)
{
aPanelA.setPanelA(iNew);
}
public void setPanelBCentral(string strNew)
{
aPanelB.setPanelB(strNew);
}
}
public class PanelA
{
int i = 0;
public void setPanelA(int iNew)
{
i = iNew;
}
}
public class PanelB
{
string str = "";
public void setPanelB(string strNew)
{
str = strNew;
}
//PROBLEM HERE HOW TO ACCESS MAIN setPanelACentral
public void changePanelA()
{
int i = 1000;
Form1.setPanelACentral(i); //<- This the part where i am asking
}
}
}
The following code demonstrates adding Events to both your Panel types and Form1. By doing this, you can raise an event in your Panel that Form1 will have registered to handle.
public partial class Form1 : Form
{
protected EventHandler<PanelEventArg> OnSetPanelA = new EventHandler<PanelEventArg>((sender, e) => { }); //stub
protected EventHandler<PanelEventArg> OnSetPanelB = new EventHandler<PanelEventArg>((sender, e) => { }); //stub
protected List<PanelBase> panels;
public Form1() : base()
{
panels = new List<PanelBase>
{
new PanelA(),
new PanelB()
};
foreach (var panel in panels)
{
OnSetPanelA += panel.OnSetPanel;
OnSetPanelB += panel.OnSetPanel;
panel.OnSomeEvent += Form1_OnSomeEvent;
}
foreach (var panel in panels.OfType<PanelB>())
{
panel.OnChangePanelA += Form1_OnChangePanelA;
}
InitializeComponent();
}
protected void SetPanelA(int iNew)
{
foreach (var panel in panels.OfType<PanelA>())
{
panel.SetPanelA(iNew);
OnSetPanelA(this, new PanelEventArg
{
Panel = panel
});
}
}
protected void SetPanelB(string strNew)
{
foreach (var panel in panels.OfType<PanelB>())
{
panel.SetPanelB(strNew);
OnSetPanelA(this, new PanelEventArg
{
Panel = panel
});
}
}
protected void Form1_OnSomeEvent(object sender, EventArgs e)
{
// handles events raised by the panel.
}
protected void Form1_OnChangePanelA(object sender, int iNew)
{
SetPanelA(iNew);
}
}
Helper Types I'm including: PanelEventArg, PanelBase
public class PanelEventArg : EventArgs
{
public PanelBase Panel { get; set; }
}
public class PanelBase //: Panel
{
public EventHandler OnSomeEvent = new EventHandler((sender, e) => { }); //stub;
public void OnSetPanel(object sender, PanelEventArg e)
{
if (!Equals(e.Panel, this))
{
//the panel being set is not this panel instance
}
}
}
Declaring PanelA and PanelB, with inheritance and new Event for PanelB
public class PanelA : PanelBase
{
int i = 0;
public void SetPanelA(int iNew)
{
i = iNew;
}
}
public class PanelB : PanelBase
{
public EventHandler<int> OnChangePanelA = new EventHandler<int>((sender, e) => { }); //stub
string str = "";
public void SetPanelB(string strNew)
{
str = strNew;
}
//PROBLEM HERE HOW TO ACCESS MAIN setPanelACentral
public void ChangePanelA()
{
OnChangePanelA(this, 1000);
}
}

How to resolve view not closing on .Close()?

I've added a DialogService in order to open a ProductView, so far the ShowDetailDialog() is working as expected.
Issue:
I call Close() on the ProductView, the view isn't closed. I debugged this issue by setting a break point on the call to the dialog service close method.
When I stepped through the code, the null check shows that productView is null, which prevents Close() from being called.
Does anyone have idea why productView is null? (although it's showing data on the view)
DialogService:(hosts the Show and Close methods)
namespace MongoDBApp.Services
{
class DialogService : IDialogService
{
Window productView = null;
ProductView _productView;
public DialogService()
{
_productView = new ProductView();
}
public void CloseDetailDialog()
{
if (productView != null)
productView.Close();
}
public void ShowDetailDialog()
{
_productView.ShowDialog();
}
}
}
ProductViewModel: (summary of ProductVM, calls the close method on SaveCommand)
private void SaveProduct(object product)
{
_dialogService.CloseDetailDialog();
Messenger.Default.Send<ProductModel>(SelectedProduct);
}
CustomerOrdersViewmodel: (Where the ShowDetailDialog() is called initially)
private void EditOrder(object obj)
{
Messenger.Default.Send<ProductModel>(SelectedProduct);
_dialogService.ShowDetailDialog();
}
This is how I have always closed my windows.
Here would be my command:
class CancelCommand : ICommand
{
private NewTruckViewModel newTruck;
public CancelCommand(NewTruckViewModel vm)
{
newTruck = vm;
}
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
newTruck.Cancel();
}
}
Here is my view Model and the method that gets called from my command:
private NewTruck myWnd; //View Declaration
//Ctor where I set myView (myWnd) equal to a view that is passed in.
public NewTruckViewModel(ObservableCollection<Truck> Trucks, NewTruck wnd, bool inEditTruck)
{
myEngine.stopHeartBeatTimer();
editTruck = inEditTruck;
myWnd = wnd;
SaveTruckCommand = new SaveTruckCommand(this);
CancelCommand = new CancelCommand(this);
ClearCommand = new ClearCommand(this);
SetLevel1MTCommand = new SetLevel1MTCommand(this);
SetLevel2MTCommand = new SetLevel2MTCommand(this);
SetLevel3MTCommand = new SetLevel3MTCommand(this);
SetLevel1FLCommand = new SetLevel1FLCommand(this);
SetLevel2FLCommand = new SetLevel2FLCommand(this);
SetLevel3FLCommand = new SetLevel3FLCommand(this);
myTrucks = Trucks;
}
public void Cancel()
{
myWnd.Close();
}
This works for me.
I resolved the issue by implementing an IDialogService on the View. Then calling the Show() and Close() methods from the ViewModel.
Solution:
Interface:
public interface IDialogService
{
void CloseDialog();
void ShowDialog(EditProductViewModel prodVM);
}
View:
public partial class ProductView : Window, IDialogService
{
public ProductView()
{
InitializeComponent();
this.DataContext = new EditProductViewModel(this);
}
public void CloseDialog()
{
if (this != null)
this.Visibility = Visibility.Collapsed;
}
public void ShowDialog(EditProductViewModel prodVM)
{
this.DataContext = prodVM;
this.Show();
}
private void Window_Closed(object sender, EventArgs e)
{
this.Visibility = Visibility.Collapsed;
}
}
ViewModel #1:
private IDialogService _dialogService;
public CustomerOrdersViewModel(IDialogService dialogservice)
{
this._dialogService = dialogservice;
}
private void EditOrder(object obj)
{
EditProductViewModel pvm = new EditProductViewModel(_dialogService);
pvm.Present(pvm);
Messenger.Default.Send<ProductModel>(SelectedProduct);
}
ViewModel #2:
private IDialogService _dialogService;
public EditProductViewModel(IDialogService dialogService)
{
this._dialogService = dialogService;
}
private void SaveProduct(object product)
{
SelectedProduct = SelectedProductTemp;
_dialogService.CloseDialog();
}
public void Present(EditProductViewModel prodVM)
{
_dialogService.ShowDialog(prodVM);
}

mef - how to make recomposition work automatically?

I've been trying to get recomposition to work but no luck... I tried many times and many approches - with no luck... can anyone point out my mistake? I expect that after I drop a new .dll into plugins directory the Senders collection will be automatically repopulated with new stuff...
//exported classes
[Export(typeof(ISender))]
public class SMTP : ISender
{
public string Name
{
get { return "SMTP plugin"; }
}
public void Send(string msg)
{
}
}
[Export(typeof(ISender))]
public class Exchange : ISender
{
public string Name
{
get { return "Exchange plugin"; }
}
public void Send(string msg)
{
// .. blah
}
}
/---------------------------------------------------------------------
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private const string STR_Pugins = ".\\plugins";
[ImportMany(typeof(ISender), AllowRecomposition = true)]
private List<ISender> Senders;
private DirectoryCatalog d;
CompositionContainer c;
public MainWindow()
{
InitializeComponent();
listBox1.DisplayMemberPath = "Name";
ConfigPlugins();
bindSenders();
}
private void ConfigPlugins()
{
DirectoryInfo dir = new DirectoryInfo(STR_Pugins);
if (!dir.Exists)
dir.Create();
d = new DirectoryCatalog(STR_Pugins);
d.Changed += new EventHandler<ComposablePartCatalogChangeEventArgs>(d_Changed);
c = new CompositionContainer(d);
c.ExportsChanged += new EventHandler<ExportsChangeEventArgs>(c_ExportsChanged);
c.ComposeParts(this);
}
void d_Changed(object sender, ComposablePartCatalogChangeEventArgs e)
{
bindSenders();
MessageBox.Show("d_Changed " + (Senders == null ? 0 : Senders.Count));
}
private void bindSenders()
{
listBox1.ItemsSource = Senders;
}
void c_ExportsChanged(object sender, ExportsChangeEventArgs e)
{
bindSenders();
MessageBox.Show("c_ExportsChanged "+ (Senders == null ? 0 : Senders.Count));
}
}
AFTER RESPONSE
ok, I've added the refresh, but still I don't get why the listbox won't populate with the new data...
public partial class MainWindow : Window
{
private const string STR_Pugins = ".\\plugins";
[ImportMany(typeof(ISender), AllowRecomposition = true)]
private List<ISender> Senders;
DirectoryCatalog d;
CompositionContainer c;
public MainWindow()
{
InitializeComponent();
listBox1.DisplayMemberPath = "Name";
ConfigPlugins();
bindSenders();
}
private void ConfigPlugins()
{
DirectoryInfo dir = new DirectoryInfo(STR_Pugins);
if (!dir.Exists)
dir.Create();
d = new DirectoryCatalog(STR_Pugins);
c = new CompositionContainer(d);
c.ComposeParts(this);
}
private void bindSenders()
{
label1.DataContext = Senders;
listBox1.ItemsSource = Senders;
}
private void button1_Click(object sender, RoutedEventArgs e)
{
d.Refresh();
bindSenders();
}
}
You have to call Refresh yourself. If you want you can use a FileSystemWatcher object to get notified when the directory contents have changed.
It won't repopulate because when the field is updated, a brand new List is set to the field. The existing collection is not modified. You have to set it up as a property instead of a field (you can still make it protected or private), then when the "set" is called, you update the listBox1.ItemsSource and the label1.DataContext.

Categories

Resources