Laden...
Avatar #avatar-3263.gif
elTorito myCSharp.de - Member
Dynamics Nav - ERP System Manager - gelernter Anwendungsentwickler Niederrhein Dabei seit 28.07.2009 177 Beiträge
Benutzerbeschreibung

Forenbeiträge von elTorito Ingesamt 177 Beiträge

04.11.2014 - 12:40 Uhr

für mich klingt es jetzt eher so als ob du das Childe Form nicht richtig Disposeds und statt es neu zu erzeugen, die gleiche Instanz benutzt und den Event Handel nochmal hinzufügst.

Ich hab nochmal drüber nachgedacht. 🤔

Irgendwie habe ich mich durch den BindingNavigator im MDI Container irr(itieren)e führen lassen...

Bis auf den BindingNavigator muss der MDI Container ja gar nicht wissen welcher DataSource das Child Form beherbergt... Und was kann der der Schon? 8o Nix...

Also im MDI Container eine Simple Button Click Funktion geschrieben, welche das Active Child ermittelt und einfach die passende Funktion dort auslöst:


private void ButtonNew_Click(object sender, EventArgs e)
        {
            var mf = this.ActiveMdiChild as MyForm;

            if (mf != null)
            {
              // successfully cast as myform
                Console.WriteLine("Active MDI Child is MYFORM and has Name " + mf.Name);
                mf.AddNewItem_Click(sender, e);
            }
            else
            {
                //cast failed
                Form f = this.ActiveMdiChild;
                Console.WriteLine("Active MDI Child is NOT myForm and has Name " + f.Name);
            }
        }

Viel weniger Code, viel einfacher zu handhaben... Also Manchmal .... :evil: Warum einfach wenns kompliziert geht ...

03.11.2014 - 13:54 Uhr

im MDI-Form abonnierst du das FormClosing des neu erzeugten Formulars mit:

frm.FormClosing += new FormClosingEventHandler(MyForm_FormClosing);  

Also ist in MyForm_FormClosing sender == frm.

Da hast du die Instanz, die du braucht.

Hallo Herbivore,

ja, vollkommen richtig ...

die foreach schleife :


private void MyForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            Form[] cForms = MdiChildren;
            foreach (Form f in cForms)
            {
                try
                {
                    MyForm mf = (MyForm)sender;
                    if (f.Name == mf.Name)
                    {

                        Console.WriteLine("CLOSING MY FORM INSTANCE");
                        mf.UpdateNavigator -= UpdateBindingNavigatorFrm; // Ereignis Abmelden
                        bindingNavigatorDeleteItem.Click -= mf.bindingNavigatorDeleteItem_Click;
                        bindingNavigatorAddNewItem.Click -= mf.bindingNavigatorAddNewItem_Click;
                        mainBindingNavigator.BindingSource = null;
                    }
                }
                catch(Exception ex)
                {
                }
            }
        }

ist völlig unnötig, der sender ist ja dass zu schliessende form ...

Habs nun vorerst so:


        private void MyForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            try
            {
                MyForm mf = (MyForm)sender;
                Console.WriteLine("CLOSING MY FORM INSTANCE");
                mf.UpdateNavigator -= UpdateBindingNavigatorFrm; // Ereignis Abmelden
                bindingNavigatorDeleteItem.Click -= mf.bindingNavigatorDeleteItem_Click;
                bindingNavigatorAddNewItem.Click -= mf.bindingNavigatorAddNewItem_Click;
                mainBindingNavigator.BindingSource = null;
            }
            catch (Exception ex)
            {
            }         
        }

Aber da muss ich eh nochmal dran und das abonnieren/verwerfen irgendwo zentral legen.

PS: Danke auch Palin für deine Antwort.

31.10.2014 - 14:26 Uhr

Hallo Herbivore,

hmm. verstehe ich nicht ganz. Ich weiß beim Öffnen/Schließen nicht um welches Form es sich handelt.

Ich öffne das Form aus dem MDI Container wie folgt:

 
MyForm frm = (MyForm)(Assembly.GetExecutingAssembly().CreateInstance(node.Form));
frm.MdiParent = this;
// Aktionen abonnieren  
frm.FormClosing += new FormClosingEventHandler(MyForm_FormClosing);
frm.UpdateNavigator += UpdateBindingNavigatorFrm; // Ereignis abonnieren

node.Form kann ein ProjectForm, CountryForm, PersonForm, ... sein...

Deswegen laufe ich alle durch beim schließen um zu schauen welches Ereignis ich von welcher Form abmelden muss. Bzw. Beim aktivieren eines anderen Offenen Form (also wenn ich z.B. von einem ProjectForm auf CountryForm wechsel) muss auch das Event für das alte Form abgemeldet werden und für das neue Aktive abboniert werden.

Was ich jetzt noch versuchen möchte ist die Events gar nicht im MDI Container zu handeln, sondern im MyForm. Würde aber heißen ich müsste aus MyForm heraus den BindingNavigator im MDI Container ansprechen, wohl keine gute Idee?

17.10.2014 - 10:22 Uhr

Hallo Herbivore,

jein, nicht ganz.

 
MyForm frm = (MyForm)(Assembly.GetExecutingAssembly().CreateInstance(node.Form));
frm.FormClosing += new FormClosingEventHandler(MyForm_FormClosing);

Wenn node.Form = "ProjektForm" ist.

Dann ist der Sender im FormClosing vom Typ ProjektForm

Ich habs nun mal so gelöst, weiß aber nicht ob das sehr elegant ist, ich gehe durch alle offenen Mdi Forms durch, versuche den Sender auf MyForm zu casten, und wenn der Name passt habe ich das Form dass ich suche.


private void MyForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            Form[] cForms = MdiChildren;
            foreach (Form f in cForms)
            {
                try
                {
                    MyForm mf = (MyForm)sender;
                    if (f.Name == mf.Name)
                    {

                        Console.WriteLine("CLOSING MY FORM INSTANCE");
                        mf.UpdateNavigator -= UpdateBindingNavigatorFrm; // Ereignis Abmelden
                        bindingNavigatorDeleteItem.Click -= mf.bindingNavigatorDeleteItem_Click;
                        bindingNavigatorAddNewItem.Click -= mf.bindingNavigatorAddNewItem_Click;
                        mainBindingNavigator.BindingSource = null;
                    }
                }
                catch(Exception ex)
                {
                }
            }            
        }

16.10.2014 - 14:06 Uhr

Hi,

also...
ich habe:

  • MDI Form
  • Eine Klasse MyForm abgeleitet von Form
  • Ein ProjektForm abgeleitet von MyForm

Aus den MDI heraus möchte ich das ProjektForm öffnen, das klappt soweit auch alles, aber ich habe Probleme mit dem Abonnieren / Verwerfen / Durchleiten von Events. Im MDI befindet sich ein BindingNavigator, dessen Add/Delete Funktionen sich im ProjektForm befinden.
(Der Hintergedanke der ganzen geschichte ist das ich mehrere Forms habe, die von MyForm ableiten, und, MyForms quasi der Verbinder zum MDI HauptForm ist, und im "ProjektForm" dann so Sachen behandelt werden wie Darstellung, Löschen usw...

Ich könnte im treeViewNode feste Forms beim anklicken hinterlegen, aber es ist so das man Nodes hinzufügen kann, und defineiren kann welches Form sich beim anklicken öffnen soll.

MyForm sieht so aus :


public partial class MyForm : Form
    {

        #region Singleton-Implementierung

        // Deklaration Singleton-Formularinstanz
        private static MyForm _singleton = null;

        /// <summary>
        /// Gibt die Singleton-Instanz des myForm Formular  zurück.
        /// </summary>
        public static MyForm Instance
        {
            get
            {
                // Wenn noch keine Singleton-Instanz existiert ...
                if (_singleton == null)
                    // Instanz erzeugen
                    _singleton = new MyForm();
                else if (_singleton.IsDisposed) // Wenn die Instanz bereits entsorgt wurde ...
                    // Instanz erzeugen
                    _singleton = new MyForm();

                // Singleton-Instanz zurückgeben
                return _singleton;
            }
        }
        #endregion

        /// <summary>
        /// Event Handler for connect Bindingingsource to Bindingnavigator in MDI FOrm 
        /// </summary>
        public class BindingSourceEventArgs : EventArgs
        {
            public BindingSourceEventArgs(BindingSource bindingSource1)
            {
                BindingSource1 = bindingSource1;
            }

            public BindingSource BindingSource1 { get; set; }// Bindingsource als  Eigenschaft definieren
        }

        public event EventHandler<MyForm.BindingSourceEventArgs> UpdateNavigator; // Ereignis deklarieren
        
        protected virtual void OnUpdateBindingNavigator(MyForm.BindingSourceEventArgs e)
        {
            EventHandler<MyForm.BindingSourceEventArgs> ev = UpdateNavigator;
            if (ev != null)
                ev(this, e); // abonnierte Ereignismethode(n) aufrufen
        }

        public virtual void bindingNavigatorDeleteItem_Click(object sender, EventArgs e)
        {
        }
        public virtual void bindingNavigatorAddNewItem_Click(object sender, EventArgs e)
        {
        }

    }

Im MDI Form erhalte ich beim Click auf einem TreeNode den Namen (als string) vom ProjektForm, und öffne das ProjektForm wie folgt:


MyForm frm = (MyForm)(Assembly.GetExecutingAssembly().CreateInstance(node.Form));
frm.MdiParent = this;
// Aktionen abonnieren  
frm.FormClosing += new FormClosingEventHandler(MyForm_FormClosing);
frm.UpdateNavigator += UpdateBindingNavigatorFrm; // Ereignis abonnieren
bindingNavigatorDeleteItem.Click += frm.bindingNavigatorDeleteItem_Click;
bindingNavigatorAddNewItem.Click += frm.bindingNavigatorAddNewItem_Click;
frm.Show();
frm.BringToFront();

im Form_Closing Event versuche ich die EventHandler wieder loszuwerden:


private void MyForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            Console.WriteLine("CLOSING MY FORM INSTANCE");
            MyForm.Instance.UpdateNavigator -= UpdateBindingNavigatorFrm; // Ereignis Abmelden
            bindingNavigatorDeleteItem.Click -= MyForm.Instance.bindingNavigatorDeleteItem_Click;
            bindingNavigatorAddNewItem.Click -= MyForm.Instance.bindingNavigatorAddNewItem_Click;
            mainBindingNavigator.BindingSource = null;
        }

Im Load ProjektForm binde ich meine gewünschte Quelle an den MDI BindingNavigator :


private void ProjectForm1_Load(object sender, EventArgs e)
{
_bindingSource.DataSource = Projects;

// Ereignis-Methode aufrufen
OnUpdateBindingNavigator(new BindingSourceEventArgs(_bindingSource));
}

Im ProjektForm überschreibe ich die Events von MyForm:


public override void bindingNavigatorDeleteItem_Click(object sender, EventArgs e){
            Console.WriteLine("DELETE in ProjektForm");
        }
        public override void bindingNavigatorAddNewItem_Click(object sender, EventArgs e)
        {
            Console.WriteLine("Add Item CLICK in ProjektForm");
           
        }

Soweit so gut, ich hab nun folgendes Problem: Wenn ich auf den BindingNavigator AddNewItem Button klicke, wird, so wie ich es möchte die Funktion

public override void bindingNavigatorAddNewItem_Click(object sender, EventArgs e)
        {
            Console.WriteLine("Add Item CLICK in ProjektForm");

        }

ausgeführt. Schließe ich nich nun das ProjektForm, und öffne es erneut, und klick auf AddItem, wird die Funktion zweimal ausgeführt. Öffne / schliesse ich das ProjektForm 5 mal, wird die Funktion 5 mal ausgelöst, immer die Anzahl der Male welche ich das ProjectForm geschlossen/geöffnet habe.

Demnach passt hier was mit der Instanz nicht. Eigentlich auch klar was nicht passt. Ich erstelle beim TreeNode Klick eine neue Instanz vom MyForm. Und im CLosing Event versuche MyForm.Instance.Event loszuwerden, ich greife also auf eine andere Instanz zu als die wo ich erstellt habe? Scheint mir zumindest so.

Ich hätte jetzt gedacht okay, mache ich aus:

MyForm frm = (MyForm)(Assembly.GetExecutingAssembly().CreateInstance(node.Form));

ein


MyForm frm = (MyForm)(Assembly.GetExecutingAssembly().CreateInstance(node.Form));
bindingNavigatorAddNewItem.Click += frm.[B]Instance[/B].bindingNavigatorAddNewItem_Click;

Aber ich hab an der Stelle kein Zugriff auf MyForm.Instance ?

Wie könnte ich mein Problem lösen?

Danke

10.10.2014 - 10:48 Uhr

Hallo,

danke für eure Antworten

Diesen konkurierenden Zugriff haben wir hier gefühlte tausend mal besprochen.
ADO.NET ist disconnected also geht das was du da beschreibst nicht

Änderungen : SqlDependency

Danke für den Hinweis. Ich hab wohl nach den falschen Stichwörtern gesucht.

SqlDependency ist nicht das was ich suche. Wenn ich richtig verstanden habe ist die Sql Dependency abhängig vom SQL Server, und muss eine offene Verbindung bereitstellen damit die Datensätze überwacht werden können.

Meine Anwendung holt sich die Daten aus der SQL Datenbank und wandelt die DataTables in Objekte um, und gibt diese weiter, ich wollte mir die Option Offen halten die Datenbank /daten Layer später mal auszutauschen, (Mysql, XML...).

Ich habe das nun wie folgt gelöst: Ich verwende ja den Zyan Server vom Rainbird, dieser stellt die Daten für meine Clients zur Verfügung. Beim Laden des Formular im Client, binde ich wie gehabt die Liste meiner Objekte (in dem Fall sind es Objekte vom Typ Projekt) ans Formular. Dann abonniere ich eine Action , der ich ein Projekt übergeben kann.

Sobald ein Projekt in der Liste geändert wird, wird die Action ausgelöst und die anderen Clients werden informiert (sofern das gleiche, passende Formular offen ist). Empfängt der Client die Änderungsbenachrichtigung, wird das Projekt in der Liste geupdatet.

Wenn also Client A und Client B gleichzeitig das Formular mit ProjektXYZ auf haben. Und Client A ändert den Namen auf ProjektABC, ändert sich bei Client B automatisch der Name in ProjektABC.

Wenn Client A das Projekt 1234 offen hat, und Client B hat das Projekt XYZ auf, und Client A ändert 1234 auf 4567, wird der Datensatz auch bei Client B in der Liste geändert, und beim Vorblättern ist dieser Aktuell.

Habe mich dabei an der Message Action orientiert welche Rainbird in seinem MiniChat Beispiel verwendet.

Die Änderungsmethode für das Objekt füge ich einer Warteschlange hinzu, die nach und nach abgearbeitet wird.

Bevor also ein Datensatz von irgendein Client geändert wird, ist dieser immer aktuell. Scheint mir zumindest so 😃

Danke

09.10.2014 - 15:32 Uhr

Hi,

meine Anwendung, ein Win Form Client, holt sich beim Öffnen eines Formular eine Liste von Objekten aus einer SQL Datenbank.

Die Liste (Array List) packe ich in eine List<T> oder ObservableCollection<T> , was auch immer...

Dann binde ich die Liste an ein BindingSource und kann mittels BindingNavigator die einzelnen Datensätze durchklickern:


 void OnLoadForm()
        {
            Project[] projectsArr = GetProjectsFromServer();
            _projects = new ObservableCollection<Project>(projectsArr);
            _binding.DataSource = _projects;
            
            OnUpdateBindingNavigator(new BindingSourceEventArgs(_binding)); 
           
            //bind the Text property on the TextBox to the ProjectName property on the Document
            projectName.DataBindings.Add("Text", this._binding, "ProjectName");

        }

Ich sehe im Formular immer nur ein Datensatz, über ListChangedEventArgs ändere ich ein Datensatz, füge hinzu oder lösche....

Klappt alles wunderbar.

Nun Folgende Situation:
Ich starte Client 1 und rufe das Formular auf, es wird das erste Projekt der Liste angezeigt. Dann starte ich Client 2 und rufe auch das Projekt Formular auf. In dem Moment hat ja jeder Client eine Liste der Projekte gebunden.

Nun ändere ich im ersten Client den Namen für Projekt1, im Client 2 kann ich munter vorwärts/rückwaerts blättern, und bekomme diese Änderung nicht mit.

Hab erst gedacht ich habe ein Fehler bei der Implementierung von INotifypropertyChanged, aber rein theoritisch wird die ProjektListe immer erst frisch geladen beim starten des Formular. Der andere Client kann also gar nicht mitbekommen das sich ein Datensatz geändert hat, sei denn (das wäre mein Gedanke jetzt um es umzusetzen) ich hole mir in Regelmässigen Abständen oder bei Gewissen Aktionen eine neue Liste oder den benötigten Datensatz neu.

Aus Dynamics NAV (mit Classic Client) kenne ich es so: dass wenn 2 Clients offen sind , und der eine ändert einen Datensatz, dann ist dieser beim anderen auch nicht direkt "sichtbar", ein paar mal vor/zurückblättern, und dann ist er da (2-3 Sek), haben beide den gleichen Datensatz offen, und der erste ändert den Datensatz, und der zweite versucht dann den Datensatz zu ändern bekommt dieser eine Fehler Meldung das der Datensatz nicht geändert werden kein weil ein anderer Teilnehmer den geändert hat, klickt man die Fehlermeldung weg, aktualisiert sich der Datensatz mit der Änderung von Client 1.

Wie handhabe ich das nun das die Datenätze zeitnah den anderen Clients meiner Anwendung zur Verfügung stehen?

Sobald ich ein Datensatz verlasse(Feld verlassen, vor/zurückblättern, Form schliessen...) , werden die Änderungen, falls vorhanden, in die Datenbank geschrieben.

Danke

08.10.2014 - 11:17 Uhr

Hi,

mal wieder übereilt nachgefragt...
Ich hatte da byte[] und Stream bisschen durcheinander gebracht.... Die Kombination machts

Bei der segmentierten Variante wird einfach nicht die komplette Datei auf einen Rutsch übertragen, sondern kleinere Batzen (auch Chunks genannt). So kann der Server bereits bei Erhalt des ersten Bytehaufenbatzen mit dem schreiben auf Platte beginnen

So habe ich das nun auch umgesetzt.

Upload: Stream wird in byte[] Häppchenweise übertragen, auf Serverseite wird byte[] in ein FileStream geschrieben, nach und nach je nach "Chunk Größe"

Download: Filestream vom Server wird als byte[] häppchenweise zurückgegeben bis Dateogröße (hole ich vorher) der Download Größe entspricht.

Danke !

07.10.2014 - 14:47 Uhr

Hi Rainbird,

über den Streaming Test Code bin ich die Tage schon gestolpert und am rumexperimentieren, aber es gelingt mir nicht:

FileServiceProxy.Listfiles gibt mir eine Liste von Dateien auf dem Server zurück, ich wähle eine aus und klicke einen Button Download:

Im Client:


var input = FileServiceProxy.GetFile(path);
var output = File.Create(dlg.FileName);

FileServiceProxy.CopyData(input, output);
input.Close();
output.Close();

Es knallt in der MessageSinkWrapper.cs in:


public IMessage SyncProcessMessage(IMessage msg)
		{
			NormalizeMessageUrl(msg);
			return InnerSink.SyncProcessMessage(msg);
		}

Fehlermeldung:
Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt.

Das gleiche wenn ich vom Client:


// Get File from Server 
var input = FileServiceProxy.GetFile(path);
var output = File.Create(dlg.FileName);
input.CopyTo(output);

wenn ich folgendes Probiere (neue connection aufbauen):


 ZyanConnection conn1 = new ZyanConnection(url, protocol, credentials, false, true);
IFileService ifrsProxy1 = conn1.CreateProxy<IFileService>();
Stream input = ifrsProxy1.GetFile(path);
var output = File.Create(dlg.FileName);
input.CopyTo(output);
// close streams
input.Close();
output.Close();

Fehlermeldung:
SocketException:Es konnte keine Verbindung hergestellt werden, da der Zielcomputer die Verbindung verweigerte

(Firewall testweise ausgeschaltet)

Muss ich ein bestimmtes Protocol verwenden für die Dateiübertragung? Momentan verwende ich dass TcpCustomServerProtocolSetup mit eigenen AuthProvider.

Danke

30.09.2014 - 12:37 Uhr

Nun aber erstmal Urlaub, danach gehts mit dem Projekt weiter 😁
gruß
Peter

2012 ... Das war (k)ein langer Urlaub ... 😁 In dem Urlaub Antrag gemacht und eins führte zum anderen... Geheiratet, Hund und Häusschen angeschafft, andauernde Kernsanierung...

Aber habe das Projekt nun mal wieder aus der Schublade gekramt 8)
Meine "Authentifizierungs" Probleme sind gelöst. Meine GUI steht soweit. So langsam muss die Anwendung ein paar "nützliche" Funktionen bekommen.

in meiner Anwendung möchte ich bestimmten Datensätzen Dateien zuordnen, diese sollen auf dem Server in ein bestimmtes Verzeichnis abgelegt werden...

Wie implementiere ich das mit dem Zyan? Hab da was gelesen von NegotiateStream ist das der richtige Ansatz?

Danke

29.09.2014 - 15:09 Uhr

Hallo Bernd,

ja, der SnapScan ist schon recht fix, tut auch schon seit Jahre guten Dienst. Für mich alleine geht s auch irgendwie, nun wollte ich aber mal meinen Eltern eine Beta meiner Anwendung zur Verfügung stellen, die aber haben ein anderen Scanner, also nicht Benutzerfreundlich das ganze.

Die Erfahrung zeigt dass das Scannen am Arbeitsplatz zu langsam ist und deshalb immer ein schneller Abteilungsscanner verwendet wird, der auf ein Server-Laufwerk scannt. In der Software werden dann nur noch die Dateien per Drag-And-Drop reingezogen.

So ähnlich mach ich das momentan mit dem ScanSnap, auf der Scan Taste ist meine Anwendung hinterlegt, wenn ich die Scan Taste drücke, wird das Dokument mit der Scanner eigenen Software eingescannt und in ein "Temp Verzeichnis" abgelegt, den Pfad nehme ich in meiner Anwendung mit
Main(string[] args) in Empfang und mach was mit.

Ich stelle mir die ganze Geschichte mit WIA bequemer vor, kann mich natürlich auch täuschen 😃

29.09.2014 - 12:37 Uhr

Hi,

ich möchte in meiner C# Anwendung die Möglichkeit haben Dokumente einzuscannen. Diese sollen dann in einer Datenbank oder in einem Verzeichnis abgelegt werden.

Ich habe derzeit ein Fujitsu Snap Scan 500 , für diesen Scanner finde ich weder WIA noch TWAIN Treiber, da scheint Fujitsu was eigenes zu haben. Mit dem S500 kann ich nur die mitgelieferte Software/Treiber benutzen und ein Programm bestimmen welches geöffnet wird, durch Angabe eines Parameter kann ich so das gescannte Dokument an meine Anwendung übergeben. Der Parameter ist die Verzeichnis Angabe des Speicherortes. Mit der Angabe kopiere ich das File und speichere es am gewünschten Ort ab... Das ist mir aber zu umständlich...

Schöner wäre wenn ich in der Anwendung eine Funktion hätte "Scannen" wo ich einen installierten Scanner auswählen kann, mir das Dokument holen, und dann was auch immer mit machen. Das möchte ich mit WIA umsetzen.

Kann mir jemand einen günstigen WIA Einzug Scanner empfehlen um meinen Fujitsu zu ersetzen?

Danke

17.09.2014 - 12:49 Uhr

Moin Moin,

das hat mir doch keine Ruhe gelassen... :evil:

ich setze meine Rollen nun wie folgt:


        // Create a generic principal based on values from the current 
        // WindowsIdentity. 
        public static GenericPrincipal GetGenericPrincipal()
        {
            // Use values from the current WindowsIdentity to construct 
            // a set of GenericPrincipal roles.
            IIdentity identity = ServerSession.CurrentSession.Identity;

            User user = UserManager.GetUser(identity.Name);
            // Add custom Roles
            int i = user.Roles.Length;
            string[] roles = new string[i];

            if (identity.IsAuthenticated)
            {
                int x= 0;
                foreach (URole r in user.Roles)
                {
                    roles[x] = r.Name;
                    x++;
                }

            }

            // Construct a GenericIdentity object based on the current  
            // identity name and authentication type. 
            string authenticationType = identity.AuthenticationType;
            string userName = identity.Name;
            GenericIdentity genericIdentity =
                new GenericIdentity(userName, authenticationType);

            // Construct a GenericPrincipal object based on the generic identity 
            // and custom roles for the user.
            GenericPrincipal genericPrincipal =
                new GenericPrincipal(genericIdentity, roles);

            return genericPrincipal;
        }

Vor dem Aufruf an an den Business Layer setze ich dann den Principal:



        public Country[] GetCountries()
        {
            Thread.CurrentPrincipal = PetersPrincipal.GetGenericPrincipal();
            return CountryManager.GetAllCountries();
        }

Im Business Layer kann ich dann wie ich es mir vorstelle die Permissions setzen:


[PrincipalPermission(SecurityAction.Demand, Role = PetersPrincipal.EmployeeRoleName)]
        public static Country[] GetAllCountries()
        {
                return CountryDal.GetAllCountries();
}

Ich selbst mach das ganze nochmal anders und injeziere den aktuellen User über ein CustomAuthorize-Attribute in die aktuelle Action. Ich nenn das ganze ActionInjection 😉
Im Attribut Infos aus Identity und Session holen und ein Objekt erstellen:
Und an der Action erwarten:

Habe ich mir auch mal angeschaut, das bezieht sich aufs MVC? aber ich denke den weg brauch ich nur wenn ich einen Web Client erstelle? Oder? , für meinen Windows Client sollte ich das nicht brauchen?

Der Ablauf ist derzeit bei mir wie folgt:

Windows Form Client:


Country[] lc = PetterApp.Business.Countries.Countries;

Shared Business Layer:


public Country[] Countries
        {
            get
            {
                return ServiceAccess.GetCountries();
            }
        }

Service Access Layer:


        public Country[] GetMvCCountries()
        {            
return CountryServiceProxy.GetCountries();
        }

CountryServiceProxy ist ein Interface und stellt die Verbindung zum Zyan Server her

Dem vom Zyan bereitgestellten Service:

        
        public Country[] GetCountries()
        {
           Thread.CurrentPrincipal = PetersPrincipal.GetGenericPrincipal();
            return CountryManager.GetAllCountries();
        }

Country Manager (Business Layer) :

  
 [PrincipalPermission(SecurityAction.Demand, Role = PetersPrincipal.EmployeeRoleName)]
        public static Country[] GetAllCountries()
        {
                return CountryDal.GetAllCountries();
}

Daten Access Layer:

  
        public static Country[] GetAllCountries()
        {
            DataTable dataTable = SqlHelper.ExecuteDataTable(GetAllCountriesStatement);
            // Umwandeln der DataTable in das zurückzugebende Country Array.
            return ConvertToCountries(dataTable);
        }

gruß
Peter

15.09.2014 - 09:44 Uhr

Guten Morgen,

danke für deine Antwort.

Wenn Du Dich in einer ASP Umgebung befindest (vermute ich wegen UserManager), dann solltest Du das Principal ohnehin NICHT über den Thread setzen (aufgrund der lokalen Zugriffe und Impersonation),

Ich befinde mich nicht in einer ASP Umgebung, **UserManager ** ist meine Business Schicht (Server -> Business Schicht -> Datenzugriff

Ich versuch(t)e dem ZyanServer vom rainbird ein eigenen Authentifizierungsanbieter vorzuschalten, das hat auch geklappt.

Dann wollte ich aber gerne die Security Abfragen in meiner "Business Schicht" beibehalten:


[PrincipalPermission(SecurityAction.Demand,Role = PetersPrincipal.CustomRoleName)]
GetCountries(){
...
}

Und deswegen kam der Gedanke "meine Rollen" einzuschleusen.

Ich denk immer zu kompliziert 😃

Ich werds dann einfach so machen:


GetCountries(){
 if  (RoleManager.IsInRole("CustomRole"))
                {
                   return CountryDal.GetAllCountries();
                }
                else {
                    throw new SecurityException("Kein CustomRole rechte");
                }
}

Erfüllt ja auch irgendwie sein Zweck. Der Benutzer ist an der Stelle so oder so schon durch den Zyan Server authentifiziert.

12.09.2014 - 18:29 Uhr

Hi,

kann man ein GenericPrincipal casten? 8)

Ich hab folgendes Problem, bzw. erhalte folgende Fehlermeldung:

Fehlermeldung:
Das Objekt genericPrincipal kann nicht nach PetersPrincipal umgewandelt werden

Ich versuche wie folgt auf **myIdentity **zuzugreifen:


PetersPrincipal.Current.myIdentity.User.Roles


public sealed class PetersIdentity : GenericIdentity{
  public User User
        {
            get
            {
                return user;
            }
        }
  public PetersIdentity (string userName):base(userName)
        {
            if (userName == null)
                throw new ArgumentNullException("user");

            this.user = UserManager.GetUser(userName);
        }
}


public sealed class PetersPrincipal: GenericPrincipal{
private PetersIdentity identity;

 public PetersPrincipal(PetersIdentity cidentity, string[] roles)
            : base(cidentity, roles)
        {
            this.identity = cidentity;
        }

public PetersIdentity myIdentity
        {
            get
            {
                return identity;
            }
        }

public static PetersPrincipal Current
        {
            get
            {
                return (PetersPrincipal )Thread.CurrentPrincipal;
            }
        }

}

Der Aufruf passiert wie folgt:


User user = UserManager.LogOn(userName, password);

if (user != null) 
            {

                int i = user.Roles.Length;
                string[] str = new string[i];

                int x= 0;
                foreach (Role r in user.Roles)
                {
                    str[x] = r.ToString();               
                    x++;
                }
PetersPrincipal pPrincipal = new PetersPrincipal(new PetersIdentity(userName), strRoleArray);

PetersPrincipal Current schmeißt die Exception bei

 return (PetersPrincipal )Thread.CurrentPrincipal;

🤔

Oder geht das gar nicht ? 🤔

Vielen Dank
gruß
Peter

09.12.2013 - 13:23 Uhr

Hi,

mit

    
public class Layout
{
   static public Color[] RedLayout = new Color[2] { Color.FromArgb(254, 255, 0, 0), Color.FromArgb(32, 255, 0, 0) };
}

ist es möglich wie folgt zuzugreifen:


Color[] xyz = Layout.GreenLayout;

Wenn ich nun meine Farbenliste in ein Dictionary packen möchte:


private static Dictionary<string, Color[]> _colorsDictionary = new Dictionary<string, Color[]>
            {
                {"RedLayout",       new Color[2] { Color.FromArgb(254, 255, 0, 0), Color.FromArgb(32, 255, 0, 0) }},
                {"GreenLayout",     new Color[2] { Color.FromArgb(254, 0, 255, 96), Color.FromArgb(32, 0, 255, 96) }}
}

Komme ich an den Wert mit :


        public static Color[] GetLayout(string selLayout)
        {
            if (_colorsDictionary.ContainsKey(selLayout))
            {
                Color[] value = _colorsDictionary[selLayout];
                return value;
            }
            else
            {
                Color[] value = _colorsDictionary["RedLayout"];
                return value;
            }
        }

Ist es möglich die Farben in eine Liste zu packen so das man einen Zugriff wie folgt erhalten könnte?:


Color[] xyz = Layout.ColorList.GreenLayout;

Danke

09.12.2013 - 09:33 Uhr

Mir gefällt die LED Anzeige noch immer gut...

Ich hab mal ein Windows Phone 7 User Control draus gemacht.
Geht wahrscheinlich schicker, und WP Konformer, aber es funktioniert...

Anstatt die Segmente im Paint zu zeichnen habe ich eine Observable Collection genommen welche beobachtet ob das gebundene Xaml Segment Objekt neu gezeichnet bzw. mit Farbe gefüllt werden muss.

Das Demo zeigt dann wie man mehrere Led Panels an eine ListBox in WP binden und anzeigen kann.

Viel Spaß damit.

27.11.2013 - 16:37 Uhr

Hi,

ich versuche mich noch immer an einer Windows Phone 7 App, und möchte in der Entwicklungsphase meine XAML Dateien mit Beispieldaten füllen.

Meine MainViewModelSampleData.xaml sieht so aus:

<local:MainViewModel
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:RaceTimer"
    xmlns:loc="clr-namespace:System.Device.Location;assembly=System.Device"
    SampleProperty="Beispielwert für die Texteigenschaft">
    <local:MainViewModel.Races>
        <local:RaceViewModel Name="Race 1"
                        LogoURI="Logo.png"
                        Description="Description of Race1">
                        <local:RaceViewModel.Persons>
                            <local:Person Name="Peter "></local:Person>
                            <local:Person Name="Claudia "></local:Person>
                        </local:RaceViewModel.Persons>
                        <local:RaceViewModel.Categories>
                            <local:Category Id="category1"
                                            Name="First"
                                            IconURI="Logo">
                                <local:Category.Dishes>
                                    <local:Dish Name="First dish title" Text="First dish text" />
                                    <local:Dish Name="Second dish title" Text="Second dish text" />
                                </local:Category.Dishes>
                            </local:Category>

                            <local:Category Id="category2"
                                            Name="Second"
                                            IconURI="Logo">
                                <local:Category.Dishes>
                                    <local:Dish Name="Third dish title" Text="Third dish text" />
                                    <local:Dish Name="Fourth dish title" Text="Fourth dish text" />
                                </local:Category.Dishes>
                            </local:Category>
                        </local:RaceViewModel.Categories>
        </local:RaceViewModel>
        <local:RaceViewModel>
         ........
        </local:RaceViewModel>
    </local:MainViewModel.Races>
</local:MainViewModel>

in meinem MainModel :

        public MainViewModel()
        {
            this.Races = new ObservableCollection<RaceViewModel>();
        }
        public ObservableCollection<RaceViewModel> Races { get; private set; }

in meiner MainPage:

           
        public MainPage()
        {
            InitializeComponent();
            DataContext = App.ViewModel;
        }

in meiner MainPage.xaml habe ich eine ListBox:

                
        <DataTemplate x:Key="ListBoxItemTemplate">
            <StackPanel Margin="0,0,0,8" Tap="Race_Click">
                <TextBlock Text="{Binding Name}" Style="{StaticResource PhoneTextLargeStyle}"
                            Foreground="White"/>
                <TextBlock Text="{Binding Description}" Style="{StaticResource PhoneTextSubtleStyle}"
                            Foreground="White"/>
            </StackPanel>
        </DataTemplate>

<ListBox 
                    Height="400" 
                    ItemTemplate="{StaticResource ListBoxItemTemplate}" 
                    ItemsSource="{Binding Path=Races}" 
                    x:Name="ReservationsListBox" 
                    toolkit:TiltEffect.IsTiltEnabled="True"/>

In dieser LixtBox zeigt der Designer auch die Daten aus der BeispielDatei an .

Mit einem Click übergebe ich einen Index an eine weitere Seite(die Seite welche nichts anzeigt):


        private void Race_Click(object sender, RoutedEventArgs e)
        {
            RaceViewModel race = (sender as StackPanel).DataContext as RaceViewModel;
            int index = App.ViewModel.Races.IndexOf(race);
            NavigationService.Navigate(new Uri("/RaceDataMainPage.xaml?index=" + index.ToString(), UriKind.Relative));

        }

Auf der neuen Seite RaceDataMainPage:


    public partial class RaceDataMainPage : PhoneApplicationPage
    {
        public RaceDataMainPage()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Overridden OnNavigatedTo handler
        /// </summary>
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);
                _raceIndex = int.Parse(NavigationContext.QueryString["index"]);

                if (_raceIndex != -1)
                {
                    DataContext = App.ViewModel.Races[_raceIndex];
                }
        }

Der Designer zeigt mir keine Daten an.
Folgende TextBox z.B.


<TextBlock Style="{StaticResource PhoneTextNormalStyle}" Text="{Binding Path=Description}" TextWrapping="Wrap"

Füge ich zur Laufzeit selber Daten ein, werden diese auch in der TextBox gezeigt. Alles WunderBar.

Wahrscheinlich übersehe ich irgendwas Grundsätzliches, um meine Beispieldaten im designer anzuzeigen. Nur was ?

Die neue Seite hat:


x:Class="RaceTimer.RaceDataMainPage"
....
mc:Ignorable="d" d:DataContext="{d:DesignData SampleData/MainViewModelSampleData.xaml}"


Es tut alles wie es soll, nur diese Voransicht auf der zweiten Seite bekomme ich nicht hin, und mir sind da gerade die Ideen ausgegangen.

Gehe ich über das Eigenschaften Fenster der ListBox auf ItemsSource, bekomme ich nur den Pfad zu Races angezeigt, darunter ist nur Count aufgelistet. Demnach habe ich mein ViewModel irgendwie falsch modeliert?

Mein RaceViewModel sieht so aus:


    public class RaceViewModel : INotifyPropertyChanged
    {
        ...
        private string _description;

        public string Description
        {
            get
            {
                return _description;
            }
            set
            {
                if (_description != value)
                {
                    _description = value;
                    NotifyPropertyChanged("Description");
                }
            }
        }
   ...
}

Ich vermute es liegt hier dran:


DataContext = App.ViewModel.Races[_raceIndex];

Aber ich komme nicht drauf. 🤔 X(

Vielleicht hat jemand eine Idee.

Danke

Peter

21.11.2013 - 17:58 Uhr

Vor allem wenn sich deine Klasse ändert die du serialisierst, dann musst du an jeder Stelle wo du manuell die XML Datei veränderst Anpassungen machen.

Ja, das macht Sinn.

Vielen Dank nochmal für deine Hilfe!

Peter

21.11.2013 - 16:34 Uhr

Hallo Xan,

ja ich hatte/habe den gleichen Stream benutzt. 😁

Ich habe jetzt 2 Streams, im ersten wird die XML Datei geladen und Deserialisiert so das ich die enthaltenen Objekte bekomme.

Dann füge ich mein neues Objekt hinzu. Und speichere den das ganze einfach neu im Stream mit FileMode.Create.

Das scheint nun so zu funktionieren.

Vielen Dank!

Darf ich vielleicht auch noch eine Doofe Anfänger Frage stellen. 8o
So wie das jetzt ist, wird die XML Datei eingelesen, ich häng mein neues Objekt dran und schicke meine ObjektListe wieder in die Datei. Das was ich zuerst vor hatte, die Datei öffnen, und nur den neuen Knoten hinzufügen, hat wahrscheinlich kein Vorteil gegenüber alles nochmal speichern?

21.11.2013 - 15:27 Uhr

Hi xan,

Ne, ich hab Open und OpenOrCreate probiert:


using (IsolatedStorageFileStream isoStream = myIsolatedStorage.OpenFile("Races.xml", FileMode.Open, FileAccess.ReadWrite))

21.11.2013 - 11:02 Uhr

Hi,

ich versuch gerade mal den Einstieg in Windows Phone App Programmierung 😁
Da ich in meiner Win8 VM keine Hardware Virtualisierung habe, und den Emulator nicht ans laufen bekomme (kein SLAT dingsda) versuche ich nun erstmal auf Windows 7 eine App für WP 7.8 zu machen.

Ok. Nach Starten der App prüfe ich ob die Datei Races.xml im IsolatedStorage vorliegt, wenn nein, dann erzeuge ich eine solche Datei:

XmlSerializer serializer = new XmlSerializer(typeof(Races));
  using (XmlWriter xmlWriter = XmlWriter.Create(stream, xmlWriterSettings))
  {
   serializer.Serialize(xmlWriter, GetRaces());
   xmlWriter.Close();
  }

<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <races>
    <race>
      <raceId>1</raceId>
      <raceName>Rennen 1</raceName>
      <racePicture>/Images/User/image.png</racePicture>
      <raceInfo>Beschreibung</raceInfo>
    </race>
     <race>...</race>
     ...
  </races>
</root>

Anschliessend lese ich die Datei aus und binde die Daten an eine ListBox:


                            XmlSerializer serializer = new XmlSerializer(typeof(Races));
                            Races races = (Races)serializer.Deserialize(str);
                            racesList.ItemsSource = races.Collection;

Nun möchte ich ein weitere Objekt Race in diese XML Datei hinzufügen:


XDocument xDoc = XDocument.Load(MyIsoStorageFileStream);
                    var newRace = new XElement("race",
                                        new XElement("raceId", txtRaceId.Text),
                                        new XElement("racenName", txtRaceName.Text),
                                        new XElement("raceInfo", txtRaceInfo.Text)
                                        );
                    xDoc.Descendants("races").FirstOrDefault().Add(new XElement(newRace));
                    xDoc.Save(MyIsoStorageFileStream);

Damit bekomme ich in der XML Datei eine doppelte Struktur, an dem was schon vorhanden war, wird das gleiche plus der neue Node noch angehängt:


<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <races>
    <race>
      <raceId>1</raceId>
      <raceName>Rennen 1</raceName>
      <racePicture>/Images/User/image.png</racePicture>
      <raceInfo>Beschreibung</raceInfo>
    </race>
  </races>
</root><root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <races>
    <race>
      <raceId>1</raceId>
      <raceName>Rennen 1</raceName>
      <racePicture>/Images/User/image.png</racePicture>
      <raceInfo>Beschreibung</raceInfo>
    </race>
    <race>
      <raceId>2</raceId>
      <raceName>Bambini Banana</raceName>
      <racePicture>/Images/testimage.png</racePicture>
      <raceInfo>Test Info </raceInfo>
    </race>
  </races>
</root>

Hab mir dann gedacht : ok, muss das ganze ja evtl. Serialisieren, mir also meine Liste geholt und das neue Element dran gehängt und dann nochmal alles abgeschickt, aber auch damit erhalte ich wie oben ein doppelten Root Tree:


                   Races loadedRaces = new Races();
                    XmlSerializer serializer = new XmlSerializer(typeof(Races));
                    Races races = (Races)serializer.Deserialize(isoStream);
                    loadedRaces.Collection =  races.Collection;

                    Race r = new Race();
                    r.raceId = "1";
                    r.raceName = "Neuer Rennen Name fistro";
                    r.raceInfo = "Neue beschreibung für fistro";

                    loadedRaces.Collection.Add(r);

                    XmlWriterSettings xmlWriterSettings = new XmlWriterSettings();
                    xmlWriterSettings.Indent = true;
                    XmlSerializer xs = new XmlSerializer(typeof(Races),"race");
                    using (XmlWriter xmlWriter = XmlWriter.Create(isoStream, xmlWriterSettings))
                    {
                        serializer.Serialize(xmlWriter, loadedRaces);
                        xmlWriter.Close();
                    }

Hmm. Wo ist mein Denkfehler?
🤔

Danke

19.11.2013 - 12:46 Uhr

Hi,

hab ne ganze Weile hin und her überlegt ob ich mein Projekt hier vorstellen soll....
Vielleicht hilft es dem ein oder anderen zu veranschaulichen wie man es NICHT machen sollte.

Folgendes ist mir bekannt, habe ich aber nicht beherzigt, aber zur Kenntnis genommen um Projekt bei gelegenheit umzubauen. 8o
Warten auf Schließen einer anderen Form [und warum man Dialoge nicht modal machen sollte]

Ich "doktor" nun schon ne ganze Weile an dem Projekt (so ca. 3 Jahre? Hobbyprogrammierer halt... 😭)
Hier gab es meine erste Frage zu diesem Projekt 8)

Naja, ich würde das Projekt gerne "Fertig" vorstellen, aber irgendwie wird es nie fertig, und da ich denke das meine jetzige Version halbwegs brauchbar ist, möchte ich die auch mal vorstellen.

Es handelt sich um einen Foto Import Assistenten. Im Windows XP Style. Ich fand es unter XP immer Klasse das der Bilder Import Assistent einem ans Händchen geführt hat. Und man nicht (wie bei Windows 7) immer alle Bilder gleich importieren muss, man konnte noch Auswählen welche man benötigt und welche nicht. Auch war es möglich mehrere Bilder gleichzeitig in verschiedene Ordner abzulegen, das ging bei Windows 7 auch nicht mehr. Und die Verschlagwortung (Markierungen) war mir sehr wichtig.

Zwar ermöglicht die Windows 7 LIVE Gallerie einen komfortableren Import als die Boardmittel. Aber den Umweg wollte ich mir sparen, bzw. wollte ich meiner Mutter ersparen , für Sie habe ich das eigentlich Programmiert. 🙂

Getestet habe ich es bisher nur auf Windows 7 64 Bit. (.Net 4)
Unter Windows 8.1 (64 bit in einer VM) läuft es, allerdings nicht durch, in der Endphase wo die Bild Dateien kopiert werden (sollten), schließt es sich. Dem muss ich noch nachgehen.

Die Zeit wo ich am meisten dran gehockt habe ist die Darstellung der Bilder in Ein/Ausklappbare Panels, was leider auch immer noch nicht 100% Sauber läuft, beim Vergrößern/Verkleinern der Ebenen flackert es bei der Neuzeichnung (noch).

Da sich die Lösung mancher Aufgaben zog, habe ich mir hier und da noch die Zeit vertrieben in dem ich die Anwendung um eine Sprache Auswahl erweiterte, und habe Log4Net als Logger implementiert um die Möglichkeit zu haben und erfahren was im Hintergrund so passiert. Da das ganze auch möglichst "Mama"freundlich sein sollte habe ich auch noch einen Installer hinzugefügt (mit WIX) auch um möglichst einfach auf Updates zu prüfen und installieren (weil wird ja nie fertig) .

Naja. Vielleicht mag der ein oder andere ja mal testen 🙂 Und falls sich jemand den Chaotischen Code antun möchte stelle ich den auch gerne zur Verfügung.

FotoImporter.zip

Die Datei beinhaltet eine Exe, 2 Sprach Ordner, 2 Dlls und eine COnfig Datei und den MSI Installer. Der Installer kopiert lediglich die Dateien ins Programmverzeichnis und erstellt eine Verknüpfung. Zumindest sollte er das :evil:

Viel Spaß beim testen.

Danke

Gruß
peter

PS: Hier noch ein paar ScreenShots

18.11.2013 - 14:17 Uhr

Vielleicht ist OpenStreetMap ne Alternative zu Google:
http://wiki.openstreetmap.org/wiki/Frameworks

18.11.2013 - 13:44 Uhr

Es wäre ausgesprochen nett, wenn jemand etwas Zeit und Lust hat, die neue 3.03 Version kurz zu testen (erfordert keine Installation,
>
).

Hi,

ich wollt das Programm grad mal testen, habs runtergeladen:

Download auto detect 32/64 bit version (recommended)

Es startet aber nicht. Nach Doppelklick auf die Ex bekomme ich sofort die Meldung "ModernView funktioniert nicht mehr" "Problemlösung wird gesucht.

Dann kommt:
Beschreibung:
Stopped working

Dateien, die bei der Beschreibung des Problems hilfreich sind:
C:\Users\Peter ***\AppData\Local\Temp\WERE640.tmp.WERInternalMetadata.xml
C:\Users\Peter ***\AppData\Local\Temp\WERFCAE.tmp.mdmp

Ich habe ein IBM Thinkpad, und Windows 7, 64 Bit und eine Mobile Intel 4 Series Grafikkarte

08.11.2013 - 18:59 Uhr

Würde vermuten hier ist eben auch
>
im Spiel. =)

Wenn dann auf jedenfall mit einem schickeren UI als das was die WIA Library mitgibt 😉

Ich habs jetzt nochmal mit WIA versucht und hinbekommen.
WIA Dialog öffnet sich, dort kann ich mein Win Phone Auswählen, anschließend kommt das Dialog Fester zum Auswählen der Bilder. Ich markiere die Gewünschten und diese werden als Image in meine Anwendung übertragen.

Nicht so schön bei der Geschichte ist das ich alle Ordner des Geräts gelistet bekomme, und mich erst durchklicken muss bis ich Bilder finde, evtl. ließe sich das auch noch Filtern.

Taugt mir trotzdem nicht die Lösung 🤔 Meine Anwendung liest Bilder von ein angegebenen Pfad ein, und ich lade Thumbnails von den Bildern in eine List<Images>. Und ganz am Ende der Anwendung kopiere ich die Bilder von Ihren Original Pfad in den gewünschten Zielpfad.

Wenn ich die Bilder via WIA in die Anwendung einlese, habe ich alle Bilder in Original Größe im Speicher, bei mein WinPhone sind das schon 2000+ Bilder, das krieg ich (noch) nicht gehandelt. Oder ich müsste die Bilder die per WIA reinkommen erst Temporär auf Festplatte speichern, das möchte ich auch nicht.

Deswegen nehme ich den WIA ExKurs mal als Erfahrung mit und die Aufgabe ist für mich gelöst.

Danke

EDIT: Wenn ich richtig gelesen habe dann sollte es recht einfach sein mit Windows 8 und VS 2013 auf das WinPhone zuzugreifen. Werd mir also mal langsam ne Win8 IDE einrichten.

Manchmal habe ich den Eindruck das MS alle alten Sachen aus dem www löscht und nur noch auf neue verweist.... :evil:

08.11.2013 - 08:55 Uhr

Hi,

danke für die Info.

Ich hab jetzt auch nochmal mit WIA probiert(Das Lumia 920 wird als WIA CameraDeviceType erkannt). Das funktioniert... Aber das auslesen dauert eeeeewig 8o

Habe versucht noch mehr Infos zu bekommen, aber so wirklich viele scheinen ein Windows Phone nicht direkt auslesen zu wollen. Und wenns doch jemand versucht ist der Vorgeschlagene Weg entweder Bilder über eine Cloud beziehen(Win Phone -> Cloud -> Desktop PC) oder aber über ein Service am Desktop, der den Port des Telefon lauscht und Bilder dann via WiIFi zum PC Übetragen werden... Letzteres scheint wohl der "übliche" Weg zu sein. Das ist mir dann doch zu viel Action. Also wird es ein feature sein das meine Anwendung nur Bilder von Removable Devices importieren kann. Schade.

Welche Technik steckt eigentlich hinter "Bilder und Videos importieren" (Rechte Maustaste auf das Media Device und Bilder und Videos importieren) ?

Danke

07.11.2013 - 15:08 Uhr

Hallo,

Mein Betriebsystem: Windows 7
Mein Phone: Lumia 920 Win8

nach Start meiner Anwendung habe ich die Möglichkeit mir über einen FolderBrowseDialog ein Verzeichnis auszusuchen. Meine anwendung durchsucht das Verzeichnis dann nach Bildern.

Im FolderBrowseDialog habe ich die Möglichkeit auf "Computer\elTorito\Phone" zu gehen bzw. dort einen Unterordner auswählen. Mache ich das, ändert der FolderBrowseDialog sofort den Status und Graut den OK Button, und den Neuen Ordner erstellen Button aus.

Gebe ich im Win Explorer in die Adresszeile den Link zum Phone direkt an:

"Computer\elTorito\Phone" erhalte ich zugriff auf die Ordner und Bilder.

Ok. Dann habe ich folgendes Probiert: über das ManagementObjectSearcher Objekt habe ich die DeviceId meines Phone ausgemacht und versuche mit einer Methode welche mir die Verzeichnisse durchsucht den Pfad "Computer\elTorito\Phone" zu übergeben, wie im Win Explorer. Das funktioniert auch nicht.

Auch wenn ich die Anwendung als Administrator ausführe, das gleiche.

Da der Zugriff über den Win Explorer klappt, hatte ich gedacht ich könne das Phone dort auswählen. Gibt es eine andere Möglichkeit um das Windows Phone nach Bildern zu durchsuchen?

Mit WIA ?

Danke

gruß
Peter

13.04.2013 - 00:51 Uhr

Nein, Visual Studio ist nicht aufwärtskompatibel. Es wird weder Windows 8 / Windows 8 Apps unterstützt noch .NET 4.5 und damit auch nicht 7.8

Okay.
Für VS 2012 gibt es aber kein Win Phone SDK? habe zumindest nichts gefunden.

Also muss ich wenn ich WIn 8 Phone Apps entwickeln möchte, einen Win 8 Desktop Rechner , bzw. ne Win 8 VM haben, um das SDK 8 installieren zu können.

Ganz schön kompliziert da durchzublicken was man braucht, und aufpassen muss man dann wohl auch für was es sein soll. 🤔

Naja, zu mein problem oben, im VS 2010 für Win Phone, werden zwar die fehlenden ressourcen angemeckert , aber die Anwendung läuft im Emulator so wie Sie soll.

Auf dem Lumia 920 ( Win8 ) sollten ja auch Win Apps für Win Phone 7.8 laufen, das sollte mir erstmal reichen. Also Freundin hat das 720 , ich hab das 920. Falls ich irgendeine App zu End ebringe soll/muss die auch auf Ihrem Handy laufen 🙂

Scheint auch gar nicht so schwer zu sein mit der App Programmierung, bisher fand ich am schwersten rauszufinden welche SDK und welche IDE ich brauche für die Entwicklung :evil:

Danke und schöne Nacht noch.

Peter

12.04.2013 - 22:40 Uhr

Hi,

nachdem ich meiner Freundin letztes Jahr schon ein Lumia 720 "aufschwatzen" konnte, habe ich nun mein N8 gegen ein Lumia 920 abgelöst, nun möchte ich mal schauen wie schwer es ist da Apps für zu Programmieren.
Also, ich habe Windows 7, habe mir die Windows Phone Developer Tools runtergeladen, SDK 7.1, auch Update auf SDK 7.8 , also ich denke habe alles was ich brauche.

Nun meine Fragen:

  1. Ist es möglich mit Betriebsystem Windows 7 Apps für Windows Phone 8 zu programmieren?

  2. Wenn ich Visual Studio Express 2010 f. Win Phone starte und ein projekt anlege, kommt zur Auswahl für welches OS es sein soll, dort bekomme ich nur Win Phone OS 7.0 und 7.1 zur Auswahl...
    (ich hätte jetzt gedacht mit Update auf SDK 7.8 ginge auch für Win Phone 7.8 (Lumia 720)

Fehlt mir doch noch ein update ?

Dann bin ich mal die Lernvideos msdn coding class: Phone Videosdurchgegangen

Warum auch immer, bekomme ich nach anlegen des Projektes nicht die Gleiche Ansicht wie in dem Video und andere Tutorials. Die Seite die den Emulator darstellen soll (Schwarzes Handy) bleibt bei mir Leer, Visual Studio meckert das einige StaticResource nicht aufgelöst werden können, könnte es daran liegen? Siehe Screenshot.

Vielen dank für eure Hilfe.

20.12.2012 - 09:08 Uhr

Guten Morgen,

evtl. kann man sich von Cobian Backup 11 (Gravity) was abgucken, oder gar verwenden falls man das Rad nicht neu erfinden möchte 😉

18.12.2012 - 10:42 Uhr

Hallo,

ich würde gerne ein simples Programm entwickeln welches bestimmte Dateien als ZIP-File komprimiert auf meinem Onlinespeicher sichert.

ich bin gerade dabei dabei so ein "simples" Backup Programm zu entwickeln, ich nehme als Basis 7z, Mein Programm Speichert/Verwaltet die "Datensicherungen" , und übergibt einfach die Parameter/Argumente und zu sichernde Liste von Ordnern/Dateien an die Console bzw. GUI von 7z weiter. 7z lasse ich in ein extra Thread laufen, und mein Programm wartet auf deren ExitCode

Ich lasse quasi ein FullBackup machen gepackt als *7z, dann folgt ein Differentielles Backup, in welchen nur die Dateien Gepackt gespeichert werden welche nicht in der FullBackup.7z enthalten sind, speichere das ganze im MS SkyDrive. 😃

Ähnlich hatte ich es schon mit Batch Dateien, so wie hier: Backup: 7-zip und batch dateien für ein automatisiertes Backup, wenn man sich dann mit den Argumenten von 7z befasst kann man damit vieles anstellen.

Die Lösung war mir aber zu kompliziert und unübersichtlich, deswegen "eigenes Progrämmchen" mit Benutzerfreundlicher GUI

17.12.2012 - 19:11 Uhr

Hi dN!3L,

danke für die Info, hab den XML Serialiser gescheut weil ich dachte wäre mehr Code Aufwand 😃
Hab mich jetzt nochmal eingelesen, und rumprobiert ...

Im nachhinein betrachtet, hätte ich spätestens nach einer Lösung für mein Problem oben weitere /andere Probleme gehabt....

Habe es jetzt mit XML Serialiser umgesetzt, ist ne Menge Code dazugekommen, aber ich habe nun eine Saubere Lösung.

Vielen dank für deine Antwort.

16.12.2012 - 13:09 Uhr

Hi,


>

opengeodb benutzen wir in der Firma zur Abfrage von PLZ's,via Webservice, der Kollege der dies eingebaut hat schwört drauf und meinte ist sehr vollständig, bei Stichproben ist mir allerdings aufgefallen das dort viele PLZ's fehlen, scheint vor allem Postfach PLZ's zu betreffen.

16.12.2012 - 12:54 Uhr

verwendetes Datenbanksystem: <XML File>

Hallo und einen wunderschönen 3te. Advent,

ich habe ein XML Dokument, dessen Knoten möchte ich als Objekte "importieren" zur späteren Weiterverwendung.

für folgende XML Struktur:

<BackupSets>
  <BackupXMLSet id="TestBack1">
    <BackupType>Full</BackupType>
    <BackupTargetDir>D:\Backups</BackupTargetDir>
    <LastFullBackupFile>D:\Backups\LastFullBackupFile.7z</LastFullBackupFile>
    <LastBackupFile>D:\Backups\LastBackupFile.Diff.7z</LastBackupFile>
    <BackupFile>D:\Backups\CurrentBackupFile.Diff.7z</BackupFile>
    <BackupLastDate>2012-12-14</BackupLastDate>
    <BackupFolderListFile>D:\Backups\backups.txt</BackupFolderListFile>
    <BackupFolderList>
      <Folder id="1">D:\Folder1</Folder>
      <Folder id="2">D:\Folder2</Folder>
    </BackupFolderList>
  </BackupXMLSet>
  <BackupXMLSet id="TestBack3">
    <BackupType>Full</BackupType>
    <BackupTargetDir>D:\Backups</BackupTargetDir>
    <LastFullBackupFile>D:\Backups\LastFullBackupFile.7z</LastFullBackupFile>
    <LastBackupFile>D:\Backups\LastBackupFile.Diff.7z</LastBackupFile>
    <BackupFile>D:\Backups\CurrentBackupFile.Diff.7z</BackupFile>
    <BackupLastDate>2012-12-14</BackupLastDate>
    <BackupFolderListFile>D:\Backups\backups.txt</BackupFolderListFile>
    <BackupFolderList>
      <Folder id="1">D:\Folder1</Folder>
      <Folder id="2">D:\Folder2</Folder>
    </BackupFolderList>
  </BackupXMLSet>

Mein Problem ist das aus dem Knoten BackupFolderList immer nur jeweils ein Eintrag genommen wird, ich hätte gerne eine Liste der Folders in BackupFolderList, als List oder IList in meinen BackupSet Objekt...

Folgender Code funktioniert, aber es wird nur der erste Folder Eintrag genommen:


var backupSetList2 = (from set in XDocument.Load(XML_FILE_NAME).Descendants("BackupXMLSet")
                                  select new BackupSet
                                  {
                                      BackupId = set.Attribute("id").Value,
                                      BackupType = set.Element("BackupType").Value,
                                      BackupFile = set.Element("BackupFile").Value,
                                      BackupFolderListFile = set.Element("BackupFolderListFile").Value,
                                      BackupLastDate = set.Element("BackupLastDate").Value,
                                      BackupTargetDir = set.Element("BackupTargetDir").Value,
                                      LastBackupFile = set.Element("LastBackupFile").Value,
                                      LastFullBackupFile = set.Element("LastFullBackupFile").Value,


                                      Logs = from b in set.Descendants("BackupFolderList").Descendants("Folder")
                                      select new Logs
                                      {
                                         Filename = b.Element("Folder").Value
                                      }
                                      

                                  });

Ich dachte, hier wäre mein Problem beschrieben, und gelöst, aber auch mit folgenden Code wird nur der erste EIntrag selektiert:


            XDocument xdoc = XDocument.Load(XML_FILE_NAME);
            var backupSetList3 = xdoc.Descendants("BackupXMLSet")
                                .OrderBy(BackupXMLSet => BackupXMLSet.Attribute("id").Value)
                                .Select(BackupXMLSet => new BackupSet()
                                {
                                    BackupId = BackupXMLSet.Attribute("id").Value,
                                    Logs = BackupXMLSet.Descendants("BackupFolderList").Select(a =>
                                        new Logs()
                                        {
                                            Filename = a.Element("Folder") != null ? a.Element("Folder").Value : null
                                        }).ToList()
                                }).ToList();

Hier noch meine Klassen:


public class BackupSet
{
     public string BackupId { get; set; }
     ...
     public IEnumerable<Logs> Logs { get; set; }
}
public class Logs
    {
        public string Filename { get; set; }
}

Vielleicht kann mir jemand auf die Sprünge helfen...

Vielen Dank

23.07.2012 - 10:39 Uhr

Hi Rainbird,

danke für die Info, werd ich mir mal durchlesen, aktuell habe ich einen "eigenen" Authentifizierungsanbieter , und zwar habe ich meinen vorhandenen einfach eingebaut:


    public class UserAuthProvider : IAuthenticationProvider
    {
		public AuthResponseMessage Authenticate(AuthRequestMessage authRequest)
		{

               // Aufruf an Geschäftslogik delegieren
               User user = UserManager.LogOn(userName, password);
            }
....
     }

Weiß aber noch nicht wie effizient das ist, ist ja quasi doppelt gemoppelt... Hintergrund war/ist folgender, ich habe eine User / Rollen Matrix Tabelle , der User meldet sich an, ich bekomme die Rollen des Users .

Auf Client Seite habe ich dann für jede Rolle eine eigene Klasse, ein Benutzer mit der Rolle Mitarbeiter loggt sich z.B. wie folgt ein:


Zyan.Business.Employees.LogOn(dlg.UserName, dlg.Password);

In der Employees Klasse erfolgt dann der Aufbau zum Zyan Server:


        private IRoles RolesServiceProxy
        {
            get
            {
                // Wenn noch kein Stellvertreterobjekt erzeugt wurde ...
                if (_rolesProxy == null)
                {
                    // Verbindung herstellen
                    TcpBinaryClientProtocolSetup protocol = new TcpBinaryClientProtocolSetup();
                    ZyanConnection conn = new ZyanConnection("tcp://meinServer:6666/elToritoSample", protocol, credentials, false, true);

                    // add global error handler
                    conn.Error += ConnectionErrorHandler;

                    // create proxy for the default queryable service
                    _rolesProxy = conn.CreateProxy<IRoles>();
                }

                // Stellvertreterobjekt zurückgeben
                return _rolesProxy;
            }
        }

und meine LogOn Methode:


        public void LogOn(string userName, string password)
        {
                // Melde den aktuellen Kunden ab.
                zyanBusiness.Customers.LogOff();

                // Melde den aktuellen Mitarbeiter ab.
                LogOff();

                // Melde den Mitarbeiter an.
                this.employee = RolesServiceProxy.LogOn(userName, password);

                foreach (Role role in employee.Roles)
                {
                    if (String.Compare(role.Name, ZyanBusiness.EmployeeRoleName, StringComparison.InvariantCultureIgnoreCase) == 0)
                    {
                        // Current user is a member of employee role.
                        return;
                    }
                }
}

Im weiteren Verlauf des Clients prüfe ich dann mit :


            // Prüfe, ob ein Mitarbeiter angemeldet ist.
            if (!zyanBusiness.Employees.IsLoggedOn)

Ob ein Mitarbeiter angemeldet ist, oder ein Customer oder eine andere Rolle, abhängig davon werden dann Menüpunkte angezeigt oder nicht, bzw. der Zugriff auf diverse Methoden erlaubt.

wobei IsLoggedOn mir nur ein Objekt User zurück gibt oder nicht:


        /// <summary>
        /// Prüft, ob aktuell ein Mitarbeiter angemeldet ist.
        /// </summary>
        public bool IsLoggedOn
        {
            get
            {
                return this.employee != null;
            }
        }

Wie gesagt, weiß noch nicht wie effizient das ist , und obs nicht eine doppelt gemoppelte Geschichte ist 🙂

Ursprünglich hatte ich mir eine Klasse von IPrincipal abgeleitet und mit :


        [PrincipalPermission(SecurityAction.Demand,Role = MeinPrincipal.EmployeeRoleName)]
        public static void DeleteCountry(Guid countryId)
        {
            CountryDal.DeleteCountry(countryId);
        }

in der BusinessLogic noch eine zusätzliche Sicherheitsprüfung eingebaut, da wollte ich nochmal schauen ob ich das mit dem Zyan auch wieder so hinbekomme,... ich hab halt das was ich schon hatte versucht zu verwenden, nun muss ich noch rausfinden was "doppelt" ist und was nicht...

Nun aber erstmal Urlaub, danach gehts mit dem Projekt weiter 😁

gruß
Peter

11.07.2012 - 16:02 Uhr

Hallo Rainbird,

danke für deine ausführliche Antwort, habe nun verstanden warum es nicht geht.

Zyan bietet aber eine Lösung für das Problem an.

Ja, da bin ich schon drüber gestolpert , hatte das Projekt auch schonmal geladen, aber es wollte einfach nicht laufen.

Wenn Dir Zyan nicht gefällt, kannst Du auch im Standard .NET Remoting eine eigene Authentifizierung implementieren. Dazu musst Du eigene Kanalsenken schreiben. Schau mal hier: MSDN: Sinks and Sink Chains

Habe ich auch schonmal probiert , aber schnell sein lassen da reichen meine Kenntnisse noch nicht für.

Habe mir jetzt nochmal das Zyan Framework geladen, wollte schon wieder nicht, nach ein wenig "Murkserei" dann doch ans laufen bekommen, einen Server erstellt, meine DAL, und BAL eingebunden, meine GUI vorgeschaltet und läuft, sowohl in der VM als auch auf den PC. Sehr schön. Dann werde ich nun mein Projekt auf den Zyan aufbauen, mal schauen wie weit ich komme. Den Server aufsetzen und die Schnittstellen implementieren sowie die GUI dran koppeln (habe mich am LINQ Beispiel orientiert) hat auf jedenfall Super schnell und problemlos geklappt.

Werde nunmal schauen wie das mit der Berechtigung geht.

Vielen Dank nochmal für deine Antwort und für die Arbeit die du /Ihr da in das Projekt gesteckt habt.

PS: Nach runterladen der Solution, wollte es mit dem kompilieren aus folgenden Grund nicht klappen:
In der Befehlszeile für Präbuildereignisse steht folgendes drin:
$(SolutionDir)tools\SnTools\sngen.bat $(SolutionDir)

Da hat der beim kompilieren ein fehler geschmissen beim ausführen der sngen.bat, und zwar wurde das Leerzeichen von ""E:\Eigene Dokumente...." nicht berücksichtigt , habe hier den Pfad hart reingeschrieben und dann hat es geklappt.

Gruß
Peter

10.07.2012 - 21:09 Uhr

Hi,

das Thema ist zwar schon ne Weile her, und gibt sicherlich schon viele andere Möglichkeiten sowas umzusetzen, dennoch habe ich hier ein Beispiel gefunden wo ich halbwegs durchblicke 😃

Ich hab deine Anwendung mal geladen, installiert, da ich das mit den DBFactorys nicht so gecheckt habe, habe ich mein schon vorhandenen DAL eingebaut damit ich meine schon vorhandenen Storage Procedures verwenden kann.

Funktioniert alles soweit Super, der Server startet, mein Client meldet sich an, Datenaustausch funktioniert Super. Danke für das Tolle Beispiel, ich finde es sehr übersichtlich.

Nun zu mein Problem:
Ich habe Win7 mit 3 Benutzer "Peter","RainBirdServer","rdu" , alle User gehören der Gruppe "Benutzer","Administratoren" und "PetersGruppe" an. PetersGruppe ist die Gruppe die ich bei deinem Setup.exe eingetragen habe.

Nun habe ich eine VM aufgesetzt wo ich den Client starte, der Benutzer der VM ist "rdu", in der VM existiert auch die Gruppe "PetersGruppe" wo "rdu" Mitglied ist.

Mit dem Benutzer "Peter" starte ich den Server , dann starte ich in der VM den Client, dieser wird auch korrekt angemeldet , sobald ich aber eine Abfrage starte knallt es bei der Rollenüberprüfung


            // Wenn der Aufrufer in der Rolle "Product Reader" ist ...
            if (ApplicationServer.IsInRole("Product Reader"))
            {
                // Aufruf an Geschäftslogik delegieren
                return new CountryManager().GetCountry(countryID);
            }
            else
                // Ausnahme werfen
                throw new SecurityException(ApplicationServer.LocalizedAccessDeniedMessage);

Bei der Überüfung von "is ApplicationServer.CurrentUser.Name trustworthy"... versucht er zu prüfen ob der der Benutzer "Peter" (der der den Server gestartet hat) Trustworthy ist.

Habe daraufhin den Benutzer Rainbirdserver angelegt, und mich mit ihm angemeldet und den Server gestartet, es passiert das gleiche, bei der Anmeldung bekomme ich ein OK zurück, alles Super, und beim Abruf von Daten knallt es , ich melde mich mit "rdu" an ok, beim Prüfen ob der Benutzer in der Rolle ist, kommt nun "is rainbirdserver" Trustworthy , das gleiche wenn ich mich mit dem Benutzer Peter anmelde, Login am Server ok, Session wird gegeben, beim Abruf von Daten ... Fehler.

Er schmeißt ein System.Security.SecurityException: Zugriff verweigert beim überprüfen von IsInRole. Wo könnte der Fehler liegen? Um auszuschließen das mein Client irgendwie murks macht habe ich mit deinem angehängten Client auch probiert, das gleiche, Login Ok, IsInRole nicht ok.

Danke!
Gruß
Peter

04.07.2012 - 12:12 Uhr

Wir haben eine Cimbali Bistro Espressomaschine 😁 , immer schön frisch und starker Kaffee , der wie auch Wasser Umsonst ist, für Cola/Fanta/Apfelschorle werden dann 0,50 Cent fällig, also bestens versorgt 🙂

Daheim habe ich eine Senseo, kaufe dafür immer Extra Starke Pads in Holland (100 Stck á ca. 5 EUR ) , ohne Kaffee geht es nicht aus dem Haus... imBüro angekommen wird dann der erste Kaffee fällig während der PC bootet, Kaffee wird dann quasi in Kette getrunken bis Nachmittags irgendwann , dann steige ich auf Wasser um, man soll ja täglich 1-2 Liter trinken. =) Und wenn ich nicht gerade an der Kaffeemaschine stehe oder auf Toilette renne , dann arbeite ich 🙂

03.07.2012 - 00:00 Uhr

Meine GUI ist ein schlechter Clone von Dynamics Nav (also MDI Anwendung) (bzw. soll mal einer werden) 😉
Ich verfluche schon den Tag an dem wir auf RoleTailored Client umstellen werden, was sich Microsoft dabei gedacht hat kann ich nicht verstehen...

02.07.2012 - 13:09 Uhr

Hi Ihr beiden,

danke nochmal für eure Antworten und Hilfe.

Einfacher geht es jedoch mit der generischen BindingList

Edit: Es könnte sich zudem lohnen die BindingList-Klasse von MS
womöglich im Zusammenhang mit einer BindingSource zu testen.

Mit BindingList funktioniert es, vielen Dank!


            IList<Country> Countries = CountryBAL.GetAllCountries();
            BindingList<Country> listOfCountries = new BindingList<Country>();
            foreach (Country land in Countries)
            {
                listOfCountries.Add(land);
            }
            listOfCountries.AllowNew = true;
            listOfCountries.AllowRemove = true;
            listOfCountries.AllowEdit = true;
            listOfCountries.RaiseListChangedEvents = true;
            bindingSource1.DataSource = listOfCountries;            
            bindingNavigator1.BindingSource = bindingSource1;
            dataGridView1.DataSource = listOfCountries;

01.07.2012 - 12:59 Uhr

Hi ,

Danke für eure Antworten, hilft mir schon weiter.

Ich hatte zu erst DataTables über BindingSource an den Bindingnavigator dran gehängt. Da klappte das (logischerweise). Nun aber habe ich meine Daten Struktur geändert und versucht die IList dran zu haengen, hätte ja klappen können, warum es nicht klappt leuchtet mir ein.

Mit BindingList hatte ich auch schon probiert, das hat auch nicht so richtig klappen wollen, gleiches Problem mit dem Add/Delete Button. Die AllwNew, Allowremove Eigenschaften sind auch true... .

Nun gut, dann müsste es aber klappen wenn ich die Buttons "manuell" implementiere? Und quasi die Events vom DataGridView abfange und an den Buttons weitergebe, bzw. andersherum.

Also Taipis Möglichkeit Nr 1. Die werde ich mal ausprobieren 😃

Danke schonmal und schönen Sonntag noch.

gruß
Peter

29.06.2012 - 18:33 Uhr

Hi,

ich binde eine Liste wie folgt an einen BindingNavigator:


            IList<Country> Countries = CountryBAL.GetAllCountries();
            bindingSource1.DataSource = Countries;
            dataGridView1.DataSource = bindingSource1;
            bindingNavigator1.BindingSource = bindingSource1;

Mit dem Binding Navigator kann ich durch die Datensätze navigieren, Vor, Zurück, Erster, Letzter...

Allerdings sind im BindingNavigator die Funktionen New, und Delete deaktiviert, wahrscheinlich weil meine Liste nur lesbar ist 😃

Tja. Und jetzt die Frage: Wie bekomme ich diese aktiviert, bzw. die Liste richtig eingebunden?

meine Struktur sieht so aus:

DAL:


        public static IList<Country> GetAllCountries()
        {
            // Laden aller Länder aus der Datenbank in eine DataTable.
            DataTable dataTable = SqlHelper.ExecuteDataTable(GetAllCountriesStatement);
            // Umwandeln der DataTable in das zurückzugebende Country IList
            return ConvertToCountries(dataTable);
        }

Mein Daten Objekt:


    public class Country
    {
        public Guid Id { get; set; }
        public string Name { get; set; }
    }

BAL:


        public static IList<Country> GetAllCountries()
        {
            return CountryDal.GetAllCountries();
        }

Danke

Gruß
Peter

22.06.2012 - 11:59 Uhr

Hi Gü,

ich denke leider immer kompliziert 😉 Nicht nur beim programmieren 😃

So einen Sauberen Weg wie du jetzt beschrieben hast, ich glaube das hätte noch ne ganze Weile gedauert bis ich dahin gekommen wäre. Das man so viel wie möglich von der UI wegdelegieren sollte versuche ich immer wieder, stolpere da allerdings auch immer wieder, wenns dann aber einmal "weg ist" fällt vieles andere einfacher. Bin jetzt seit ca. 2 Jahren an dieser Anwendung dran, und immer wieder finde ich Sachen die ich dann doch auf einmal in irgendwelche Klassen packen kann , macht die ganze Sache viel übersichtlicher.

Bleibt mir noch ein großes Dankeschön für deine Hilfe

Gruß
Peter

21.06.2012 - 18:50 Uhr

Hi Gü,

danke nochmal.

Habe nun folgendes gemacht, den Backgroundworker ganz raus....
in meinen Form welches die Server Liste anzeigen soll folgendes im Load:



        private void frmSQLServer_Load(object sender, EventArgs e)
        {
            if (_serverList.Count == 0)
            {
                toolStripStatusLabel1.Text = "Server werden gesucht...";
                try
                {
                    TaskScheduler uiThread = TaskScheduler.FromCurrentSynchronizationContext();

                    Action MainThreadDoWork = new Action(() =>
                    {
                        // SQL Server Liste Laden 
                        Console.WriteLine("Hard Work here...");
                        _serverList = LocateSqlInstances();
                    });

                    Action ExecuteProgressBar = new Action(() =>
                    {
                        toolStripStatusLabel1.Text = "Server werden gesucht...";
                    });

                    Action FinalThreadDoWOrk = new Action(() =>
                    {
                        toolStripStatusLabel1.Text = "Server Liste geladen...";
                        FillDataGrid();
                    });
                    Task MainThreadDoWorkTask = Task.Factory.StartNew(() => MainThreadDoWork());
                    Task ExecuteProgressBarTask = new Task(ExecuteProgressBar);
                    ExecuteProgressBarTask.RunSynchronously();

                    MainThreadDoWorkTask.ContinueWith(t => FinalThreadDoWOrk(), uiThread);
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error", ex.Message);
                }
            }
            else
            {
                Console.WriteLine("Soft Work here ... ");
                FillDataGrid();
            }
        }
        // Notify when task is cancelled
        public void cancelNotification()
        {
            Console.WriteLine("Cancellation request made!!");
        }

Wenn das Formular geschlossen wird dann : cTokenSource.Cancel();

Ahso, und statt den Modalen Dialog, hab ich einfach in die Statusbar einen Text reingesetzt 😉 Wäre das auch weg 😃 Server Liste wird im Hintergrund behalten, falls Form wieder aufgerufen wird...

Ich denke so müsste das passen...

Nochmal zum Verständnis: Die Tasks sind jetzt das Neue Backgroundworker?

Und um den Code (den ich mir zusammen geklaut habe) zu verstehen, Erst startet der Task MainThreadDoWork, und Synchron dazu startet der Task ExecuteProgressBarTask, und wenn Task MainThreadDoWork zu Ende ist mache weiter mit FinalThreadDoWOrk.

Danke.
Gruß
Peter

21.06.2012 - 15:55 Uhr

Hi Gü,

erstmal danke für deine ANtwort.

ArrayList gehört in die Mottenkiste

schon ausgetauscht 😉 Falle ich immer wieder drauf rein obwohl ich List<T> nun schön öfter bei anderen Sachen verwendet habe 😃

Für die modalen Dialoge schau dir auch die Überlegungen

Danke für den Hinweis. Liest sich sehr gut der Artikel und ist auch sehr verständlich. Habe für das Server Listen Loading einen modalen Dialog bevorzugt weil ohne Server Auswahl rein theoritisch eh keine Bedienung möglich sein soll. Letztendlich aber arbeitet meine Anwendung (bis jetzt) aber tatsächlich so das ein komplettes sperren nicht nötig ist.

PS: Dass GetDataSources nur für SQL Server 2000

Ich hab ein SQL Express Edition with Advanced Services 64 Bit (10.50.2500),

zum eigentlichen Problem:

Habe ich nun wie folgt gelöst:

  1. Anwendung wird gestartet (MDI Container)

  2. Datenbank Verbindungs Form wird gestartet

  3. Beim starten dieser Form erstelle ich ein Task und starte diesen, der Task macht genau das was mein obiger bw_DoWork machte (mit dem Unterschied das er nun die Server Strings in eine List<string> packt 😉 )

  4. Der LocateSQLServer Task bekommt ein Cancel Token

  5. Ein zweiter Task startet mit ContinueWithTask , sobald der erste Task fertig ist (damit ich weiß das die ServerListe geladen wurde, oder auch nicht...

  6. im Datenbank Verbindungs Form cklicke ich ein Button "Server auswählen"

  7. Nach dem Cklick prüfe ich als erstes ob die Liste mit Servern schon verfügbar ist , falls ja, Form starten, DataGrid füllen, fertig...

  8. Falls nein, öffne ich mein (noch ) DialogFenster mit der Progress anzeige

  9. Direkt danach startet mein Backgroundworker der nun folgendes macht:


        private void bw_DoWork(object sender, DoWorkEventArgs e)
        {

            // Do some long running task...
            while (!m_fmProgress.Cancel)
            {
                // Do Nothing until: 
                if (serverListLoaded)
                    break;
            }
            // Periodically check for a cancellation
            // If the user clicks the cancel button, or tries to close
            // the progress form, the m_fmProgress.Cancel flag
            // will be set to true.
            if (m_fmProgress.Cancel)
            {
                // Set the e.Cancel flag so that the WorkerCompleted event
                // knows that the process was cancelled.
                e.Cancel = true;
                // cancelling task
                cTokenSource.Cancel();
                return;
            }
        }
  1. Wird abbrechen geklickt oder ESC, schließt sich das ProgressForm direkt wieder und ich teile dem Task ein Cancel mit, kommt auch bei dem an, im Hintergrund wird die Server Liste munter weiter geladen und füllt meine List<string>
  2. Beim nächsten Click auf das Server Listen Form steht die Liste somit sofort zur verfügung.
  3. Falls ich das Progress Form nicht abbreche, bleibt es auf dem Schirm bis der Zweite Task beendet ist, der Zweite Task setzt lediglich ein serverListLoaded = true, damit ich meinen Backroundworker Completed signalisiern kann und im Copmpleted dann auch das Form aufmacht mit der Server Liste.

Also ich denke mit der Lösung kann ich Leben, werde das aber nochmal ändern, und zwar so das der Task der die ServerListe laden soll, vom Form aus angestoßen wird in welchen auch die Liste angezeigt wird, in dem Form das jetzt den Task anstößt kann man rein theoritisch auch einen ServerName String in ein TextFeld schreiben, in dem Falle brauch ich ja nicht schon beim Laden dieses Form nach Servern zu suchen.

Danke.

gruß
Peter

20.06.2012 - 18:14 Uhr

Hi,

ich möchte eine Liste von SQL Servern in ein neues Form laden, dafür habe ich ein Button der einen Backgroundworker startet, gleichzeitig auch ein Form welches signalisiert das Server gesucht werden, das funktioniert auch alles wunderbar, der Backgroundworker macht seine Arbeit, und wenn die fertig ist (Liste mit SQL Servern) wird das Ladebalken/Progressfenster geschlossen, und die Liste an an mein gewünschtes Form übergeben.

Mein Problem ist der Abbruch, dem ProgressForm teile ich mit ob Abbrechen geklickt wurde (m_fmProgress.Cancel), darauf soll der Backgroundworker reagieren, tut er aber nicht.

Tut er schon, solange ich (if (m_fmProgress.Cancel)) in einer for oder while Schleife drin habe , ich habe nun mit verschiedenen anderen "HardWork" Funktionen probiert, und sobald ich in meinen ProgressForm abbrechen klicke, wird abgebrochen und das Form geschlossen.

Ich vermute daher das der Hund bei
DataTable sqlSources = SqlDataSourceEnumerator.Instance.GetDataSources()
begraben liegt...

Ich bekomme dort immer von sqlSources.Rows.Count etwas zurück, egal ob ich abbreche oder nicht. Im Falle von Abbrechen, bekomme ich die Anzahl der Server zurück, die folgende Foreach Schleife wird dann ignoriert.

Nun die Frage: Wie kann ich** SqlDataSourceEnumerator.Instance.GetDataSources** unterbrechen?

Vielen Dank

Der Button startet den BW :


       private void btnServerNameLookup_Click(object sender, EventArgs e)
        {
               BackgroundWorker bw = new BackgroundWorker();
                bw.WorkerSupportsCancellation = true;
                bw.DoWork += new DoWorkEventHandler(bw_DoWork);
                bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
                

                // Create a progress form on the UI thread
                m_fmProgress = new fmProgress();

                // Kick off the Async thread
                bw.RunWorkerAsync();

                // Lock up the UI with this modal progress form.
                m_fmProgress.ShowDialog(this);
                m_fmProgress = null;
         }

Mein DoWork:


private void bw_DoWork(object sender, DoWorkEventArgs e)
        {
            ArrayList servers = new ArrayList();
            
            using (DataTable sqlSources = SqlDataSourceEnumerator.Instance.GetDataSources())
            {
            Console.WriteLine(sqlSources.Rows.Count);            
            if (m_fmProgress.Cancel)
            {
                e.Cancel = true;
                return;
            }
            foreach (DataRow source in sqlSources.Rows)
                {
                    string servername;
                    string instanceName = source["InstanceName"].ToString();

                    if (!string.IsNullOrEmpty(instanceName))
                    {
                        servername = source["InstanceName"] + "\\" + source["ServerName"];
                    }
                    else
                    {
                        servername = source["ServerName"].ToString();
                    }
                    servers.Add(servername);
                    Console.WriteLine(" Server Name:{0}", servername);
                    Console.WriteLine("     Version:{0}", source["Version"]);
                    Console.WriteLine();

                }

            }
        }

Wenn fertig:


        private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            // Hide the Progress Form
            if (m_fmProgress != null)
            {
                m_fmProgress.Hide();
                m_fmProgress = null;
            }

            // Check to see if an error occurred in the
            // background process.
            if (e.Error != null)
            {
                MessageBox.Show(e.Error.Message);
                return;
            }

            // Check to see if the background process was cancelled.
            if (e.Cancelled)
            {
                MessageBox.Show("Processing cancelled.");
                return;
            }

            // Everything completed normally.
            // process the response using e.Result
            MessageBox.Show("Processing is complete.");

19.06.2012 - 09:41 Uhr

Ich vermute weiterhin, dass Variante 1 nur laufende Instanzen findet, während Variante 2 die installierten Instanzen zeigt, auch wenn diese nicht laufen.

Hi MarsStein,

ja, scheint als wenn das so ist.
Sofern der SQL Browser läuft werden auch nicht laufende aber installierte Instanzen angezeigt.
Ich entscheide mich mal für Variante 2 😃

Vielen Dank.

18.06.2012 - 17:12 Uhr

SQL Express Edition with Advanced Services 64 Bit (10.50.2500)

Hi,

für meine Anwendung möchte ich eine Liste der Verfügbaren SQL Server Instanzen, die Liste bekomme ich auf 2 unterschiedlichen Wegen:


        public static ArrayList GetSqlServerInstances()
        {
            ArrayList servers = new ArrayList();

            // Holen der verfügbaren Server mit einem SqlDataSourceEnumerator
            SqlDataSourceEnumerator enumerator = SqlDataSourceEnumerator.Instance;
            DataTable serverTable = enumerator.GetDataSources();

            //Alle verfügbaren Instanzen sammeln
            foreach (DataRow row in serverTable.Rows)
            {
                string serverName = row["ServerName"].ToString();

                if (row["InstanceName"] != DBNull.Value)
                {
                    serverName += "\\" + row["InstanceName"];
                }

                servers.Add(serverName);
            }
            return servers;
        }

oder


        public static ArrayList GetSQLServerInstancesByReg()
        {
            ArrayList servers = new ArrayList();
            RegistryKey rk = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Microsoft SQL Server");
            String[] instances = (String[])rk.GetValue("InstalledInstances");
            if (instances.Length > 0)
            {
                foreach (String element in instances)
                {
                    string serverName;
                    
                    if (element == "MSSQLSERVER")
                        serverName = System.Environment.MachineName;
                    else
                        serverName = System.Environment.MachineName + @"\" + element;
                    
                    servers.Add(serverName);
                }
            }
            return servers;
        }

Variante 2 (über die Registry) liefert die Liste wesentlich schneller als Variante 1 über den DataSourceEnumerator, was sollte ich bevorzugen?

Vielen Dank