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

Forenbeiträge von elTorito Ingesamt 177 Beiträge

24.06.2020 - 00:46 Uhr

Hallo,

habe ein problemchen mit Visual Studio Community 2019

ich habe eine C# UWP App welche 2 Hintergrunddienste ausführt.

Über Debugspeicherort löse ich die Hintergrund Aufgabe aus, und konnte dann den Quellcode Debuggen. Im Backgroundtask habe ich diverse System.Diagnostics.WriteLine.

Das hat auch alles wunderbar funktioniert, bis ich STRG+UMSCHALT+F9 (Alle Haltepunkte löschen) angeklickt habe, jetzt komme ich mit dem Debugger nicht mehr in den Hintergrundtask rein (trotz Breakpoint) , und die System.Diagnostics des Backgroundtask schreibt auch nichts mehr in die Ausgabe.

PS: Habe nun versucht die App auf dem Remotecomputer zu Debuggen. Da bekomme ich gar keine Diagnostics.WriteLine , und Haltepunkte funktionieren da auch nicht einmal in der Vordergrund App.

Wird mit Alle Haltepunkte löschen evtl. noch irgendeine Einstellung verändert die ich jetzt wieder auswählen muss?

Danke

21.12.2016 - 14:16 Uhr

verwendetes Datenbanksystem: Sql2008R2

Hi,

vielleicht kann mir hier jemand helfen, ich wundere mich über die Ergebnisse einer SQL Volltextsuche... Siehe Anhang.

Ich habe 2 Suchbegriffe, und möchte Alle Datensätze finden in welchen beide Suchbegriffe vorkommen (Spaltenunabhängig). Es soll ein Treffer gelandet werden wenn, egal in welcher Spalte, beide Suchbegriffe vorkommen. Wenn ein Begriff ein Beschreibung, und der andere in Beschreibung 2 soll auch ein Treffer sein.

Im Anhang habe ich 2 Testsuchen, und frage mich warum der Artikel 000979 nicht gefunden wird.
Im VolltextKatalog sind die entsprechenden Felder indiziert.

Nun habe ich mir gedacht es wäre doch toll wenn es eine Möglichkeit gäbe, die mir sagt, Treffer 1,2, und 3 wurde gefunden weil Suchbegriff in Spalte X, und Suchbegriff in Spalte Y... Um ausschließen zu können dass die hier nur Felder Berücksichtigt werden in denen beide Suchbegriffe vorkommen.

Kann man so etwas realisieren? Oder hat jemand ein Tipp warum der 00979 nicht gefunden wird mit den Suchbegriffen des Beispiel?

Danke

11.10.2016 - 07:35 Uhr

Hi,

ich habe VS Community 2015 Version 14.0.25431.01 Update 3

Es gab in älteren VS Versionen mal die Funktion (Maus rechtsklick im Codefenster -> Unit Test erstellen), die wurde dann bei einigen Visual Studios rausgenommen und soll ab 2015 wieder vorhanden sein. (Add "Create Unit Tests" menu option back!) oder Unit Test Generator

Bin auch schon über Extras - Anpassen ContextMenü, finde es dort aber auch nicht.

Betrifft das nur eine Spezielle VS 2015 version?

Danke

04.10.2016 - 12:51 Uhr

Hi,

danke für eure Antworten ...

Hab nochmal geschaut. Das Binding geht. 😁
Ich hatte vergessen dem Model mitzteilen das s sich etwas geändert hat.

ich hatte:


public bool CanEditGame => this.GameState == GameStatus.NotStarted;

und


public GameStatus GameState
        {
            get
            {
                return _gameStatus;
            }
            set
            {
                if (_gameStatus != value)
                {
                    _gameStatus = value;
                    NotifyPropertyChanged(nameof(CanEditGame)); // <- hinzugefügt 
                }
            }

Nun geht es. 👍
(Freitag Nachmittags vor nem langen Wochenende halt, da sieht/findet man nichts mehr 🤔 ) ...

Danke

30.09.2016 - 15:55 Uhr

Hi,

Ich habe eine Page mit einem ListView wo ich CanReorderItems = true setze.

Ist es möglich diese Eigenschaft an einer Eigenschaft meines Model zu binden?


 <ListView 
                        x:Name="PlayersListView"
                        ItemsSource="{Binding Game.Players}"
                        CanReorderItems="True">
                        </ListView>

Ich hätte gerne :


 <ListView 
                        x:Name="PlayersListView"
                        ItemsSource="{Binding Game.Players}"
                        CanReorderItems="{Binding Game.CanEditGame}">
                        </ListView>

funktioniert aber nicht , ich kann trotzdem noch neu Sortieren.

Danke

28.06.2016 - 07:33 Uhr

Ich hab neulich mal das Azure Angebot getestet, Dienst und SQL DB auf Azure veröffentlichen, mit SQLite Offline Sync . Ging schnell zu konfigurieren, funktioniert gut.
Bietet viel, leicht erweiterbar... Finde aber das Preismodell etwas teuer.

07.06.2016 - 15:17 Uhr

Ja, die "Schnellaktionen und Refactorings" sind noch nicht so mächtig, wachsen aber mit jeder Version. Wenn die Lampe leuchtet, aber nichts passiert, betrachte das als "reserved for future use" 😉.

👍

Danke für eure Antworten. 👍

07.06.2016 - 15:02 Uhr

Hättest Du OOP verwendet und eine entsprechende Basisklasse, dann könntest es zentral an einer Stelle ändern 😃
So ist es eine Lehrstunde oder Du verwendest Search and Replace mit Regex.

Puh... Jetzt musste ich kurz überlegen, aber ich denke schon ich hab OOP und auch eine Basisklasse, jetzt war ich kurz verwirrt und am grübeln "Wie? das ist nicht oop was ich mache?" ...

Muss(te) den Typ wirklich nur an einer Stelle ändern, habe allerdings ein "Dummy Service" der mir TestDaten generiert, sonst alles gut.

Ja, mache das sonst auch so, ändern bis alle Build Fehler weg sind.

Ich dachte evtl. sei es möglich mit dem Punkt "Schnellaktionen und Refactorings" welcher ganz oben erscheint wenn man rechte Maustaste im Code klickt. Wenn ich da anklicke passiert allerdings nichts.

07.06.2016 - 14:48 Uhr

Hi,

in VS ist es ja möglich eine Klasse umzubenennen und diese wird dann überall im Projekt abgeändert.

Ist es auch möglich auf diese Art und Weise ein datentyp zu ändern?

Also ich hab z.b.

public class HelloClass
{
public string Id{get;set;
}

und möchte nun aus string ein int machen, muss dann anschließend alle funktionen welche den Typ string erwarten abändern.

geht das evtl. einfacher?

Vielen Dank

27.02.2016 - 00:00 Uhr

So. eine "K.I." habe ich fertig 😁

Ich Unterteile in Punkte Segmente:
Score >170 (High Segment)
Score > 120 && Score ≤ 170 (Medium Segment)
Score ≤ 120 && Score ≥ 60 (low Segment)
Score < 60 (Low segment)

Für jedes Segment habe ich eine Liste mit den Zahlen und Multipliktoren die in dem Segment getroffen werden können, so wie eine Liste mit den angrenzenden Feldern:


public static List<int> ExtremHighSegmentTargetNumbers = new List<int>
        {
            20,
            19,
            18,
            17
        };
 public static List<int> ExtremMediumSegmentTargetNumbers = new List<int>
        {
            25,
            20,
            19,
            18,
            17,
            16,
            15,
            14,
            13,
            12,
            11,
            1
        };
public static List<int> ExtremLowSegmentTargetNumbers = new List<int>
        {
            25,
            20,
            19,
            18,
            17,
            16,
            15,
            14,
            13,
            12,
            11,
            10,
            9,
            8,
            7,
            6,
            5,
            4,
            3,
            2,
            1,

        };

 public static List<HitTarget> ExtremHighSegmentHitTargets = new List<HitTarget>
        {
            HitTarget.Triple,
            HitTarget.Single
        };

 public static List<HitTarget> ExtremMediumSegmentHitTargets = new List<HitTarget>
        {
            HitTarget.Triple,
            HitTarget.Single,
            HitTarget.Double
        };
public static List<HitTarget> ExtremLowSegmentHitTargets = new List<HitTarget>
        {
            HitTarget.Triple,
            HitTarget.Single,
            HitTarget.Double,
            HitTarget.Out
        };

public static Dictionary<int, List<int>> ExtremHighSegmentNearTargetNumbers = new Dictionary<int, List<int>>
        {
            {20, new List<int>{5,1}},
            {19, new List<int>{7,3}},
            {18, new List<int>{1,4}},
            {17, new List<int>{3,2}},
        };

public static Dictionary<int, List<int>> ExtremMediumSegmentNearTargetNumbers = new Dictionary<int, List<int>>
        {
            {25, new List<int>{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20}},    
            {20, new List<int>{5,1}},
            {19, new List<int>{7,3}},
            {18, new List<int>{1,4}},
            {17, new List<int>{3,2}},
            {16, new List<int>{7,8}},
            {15, new List<int>{2,10}},
            {14, new List<int>{11,9}},
            {13, new List<int>{4,6}},
            {12, new List<int>{5,9}},
            {11, new List<int>{14,8}},
            {1, new List<int>{20,18}},
        };

public static Dictionary<int, List<int>> ExtremLowSegmentNearTargetNumbers = new Dictionary<int, List<int>>
        {
            {25, new List<int>{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20}},    
            {20, new List<int>{5,1}},
            {19, new List<int>{7,3}},
            {18, new List<int>{1,4}},
            {17, new List<int>{3,2}},
            {16, new List<int>{7,8}},
            {15, new List<int>{2,10}},
            {14, new List<int>{11,9}},
            {13, new List<int>{4,6}},
            {12, new List<int>{5,9}},
            {11, new List<int>{14,8}},
            {10, new List<int>{6,15}},
            {9, new List<int>{14,12}},
            {8, new List<int>{11,16}},
            {7, new List<int>{19,16}},
            {6, new List<int>{10,13}},
            {5, new List<int>{12,20}},
            {4, new List<int>{18,13}},
            {3, new List<int>{19,17}},
            {2, new List<int>{17,15}},
            {1, new List<int>{20,18}},
        };

Damit erzeuge ich je nach Segment eine Liste mit den möglichen Treffern in dem Segment:


 public static List<DartShoot> InitialShoots( List<int> initNumbers, List<HitTarget> initHitTargets, Dictionary<int, List<int>> dictNearShoots)
        {
            List<DartShoot> list = new List<DartShoot>();

            foreach (int i in initNumbers)
            {
                foreach (HitTarget t in initHitTargets)
                {
                    if (i == 25 && t == HitTarget.Triple)
                    {

                    }
                    else
                    {
                        list.Add(new DartShoot() { HitNumber = i, HittedTarget = t, NearShoots = GetNearShoots(i, dictNearShoots) });
                    }
                }
            }

            return list;
        }

Für die möglichen Treffer lade ich die anliegenden Felder :


public static List<DartShoot> GetNearShoots(int hitno, Dictionary<int,List<int>> dict)
        {
            List<DartShoot> list = new List<DartShoot>();
            if (dict.ContainsKey(hitno))
            {
                List<int> iList = dict[hitno];
                foreach (int i in iList)
                {
                    list.Add(new DartShoot() { HitNumber = i, HittedTarget = HitTarget.Single });
                    list.Add(new DartShoot() { HitNumber = i, HittedTarget = HitTarget.Double });
                    if (i != 25)
                        list.Add(new DartShoot() { HitNumber = i, HittedTarget = HitTarget.Triple });
                    list.Add(new DartShoot() { HitNumber = i, HittedTarget = HitTarget.Out });
                }
            }
            return list;
        }

Im Segment > 170:


listAllShoots =  DartShootsDict.ExtremHighSegment();
int initialTargetNo = EnumerableExtensions.RandomEnumValue(DartShootsDict.ExtremHighSegmentTargetNumbers, new Random()).First();
IEnumerable<DartShoot> list = from shoot in listAllShoots
                                              where ((shoot.HitNumber == initialTargetNo) && shoot.HittedTarget == HitTarget.Triple && shoot.HittedTarget != HitTarget.Out)
                                              select shoot;
                    
               
                IEnumerable<DartShoot> nearShootList = null;
                foreach(DartShoot s in list)
                {
                    if (s.NearShoots != null)
                    {
                        nearShootList = list.Concat(new List<DartShoot>(s.NearShoots));
                    }
                }

                HitTarget selHitTarget = EnumerableExtensions.RandomEnumValue(DartShootsDict.ExtremHighSegmentHitTargets, new Random()).First();
                IEnumerable<DartShoot> hittargetlist = from shoot in nearShootList
                                                       where (shoot.HittedTarget == selHitTarget)
                                                       select shoot;
DartShoot ds = EnumerableExtensions.RandomEnumValue(hittargetlist, new Random()).First();

Im Medium / Low Segment :


IEnumerable<DartShoot> list = from shoot in listAllShoots
                                              where ((shoot.HitNumber == initialTargetNo)) 
                                              select shoot;

Low Segment unter 60 Punkte:


IEnumerable<DartShoot> list = from shoot in listAllShoots
                                              where ((shoot.HitNumber == initialTargetNo && shoot.HittedTarget == HitTarget.Double))
                                              select shoot;

Unter 50 Punkte lasse ich noch eine Schleife laufen, welche alle Zahlen/2 prüft, und dann zufällig auswählt ob der Dart gewinnt oder ob es doch ein Zufallswurf wird:


private DartShoot GenerateRandomLowScoreShoot(int doubleNo)
        {
            bool finish = EnumerableExtensions.RandomEnumValue(DartShootsDict.BOut, new Random()).First();
            
            if (finish)
            {
                System.Diagnostics.Debug.WriteLine("Direct Out Shoot ");
                return new DartShoot() { HitNumber = doubleNo, HittedTarget = HitTarget.Double };
            }
            else
            {
                IEnumerable<DartShoot> lds = from shoot in DartShootsDict.ExtremLowSegment()
                                             where ((shoot.HitNumber == doubleNo && shoot.HittedTarget == HitTarget.Double))
                                             select shoot;
                IEnumerable<DartShoot> nearShootList = null;
                foreach (DartShoot s in lds)
                {
                    if (s.NearShoots != null)
                    {
                        nearShootList = lds.Concat(new List<DartShoot>(s.NearShoots));
                    }
                }
                HitTarget selHitTarget = GetRandomTarget(doubleNo, DartShootsDict.ExtremLowSegmentHitTargets);
                IEnumerable<DartShoot> hittargetlist = from shoot in nearShootList
                                                       where (shoot.HittedTarget == selHitTarget)
                                                       select shoot;
                return EnumerableExtensions.RandomEnumValue(hittargetlist, new Random()).First();
            }
        }

Hab jetzt paar Spielchen gemacht, die K.I. pendelt so zwischen Average 60 und 113 derzeit, und braucht 13 bis 25 Darts zum ausmachen , also recht große Streuung, werde da noch bisschen dran "pfeilen" 🙂 Im Unteren Segment überwirft die KI sich zu Oft. (2-3 mal) dass sind dann die 6-9 Darts Unterschied zwischen Profi und Amateur ungefähr.

Wünsche ein schönes Wochenende

Code werde ich noch aufräumen ...

Peter

26.02.2016 - 10:39 Uhr

Hallo,

danke für eure Antworten.

Sind ja einige Möglichkeiten dabei. 👍
Ganz kompliziert wollte ich es nicht machen.

Ich überlege nun wie folgt:

Am Anfang eine Liste mit allen möglichen Wurf Varianten (wie trib meinte), je nach Spielphase und Level des Spieler wird die Liste abgespeckt. Dann weiter entscheiden um die Liste evtl noch weiter zu reduzieren, und von dem was über bleibt hole ich mir ein Zufallswurf.

z.B. Profi Level:
Spiel fängt bei 501 Punkten an
ich biete an:
20,19,18,17

entscheide mich für die T20 und biete an:
T20,S20,T1,S1,T5,5

Anschliessend entscheiden, Treffer auf T20 oder Zufall(S20,T1,S1,5,T5)

Beim Semi Profi z.B. am Anfang:
Die Felder welche dem Profi angeboten wurden plus die angrenzenden Felder:
20,1,5,18,4,19,7,3,2

ich entscheide mich dafür dass er auf T18 geht und biete an:
T18,S18,D18,S1,D1,T1,S4,D4,T4, Out

So irgendwie stell ich mir das nun vor.

25.02.2016 - 10:14 Uhr

Hi,

ich möchte meine DartsApp um einen Computer Spieler erweitern.

Ich brauche für einen Wurf eine Nummer und ein Multiplikator (x1,x2,x3).

Mein erster Ansatz war eine fertiges Dictionary mit Fertigen Spielwürfen:


Dictionary<int, List<DartShoot>>ComputerPersonsShoots = new Dictionary<int, List<DartShoot>>
        {
            {0, new List<DartShoot>
                {
                    new DartShoot(){HitNumber=20,HittedTarget=HitTarget.Triple},
                    new DartShoot(){HitNumber=20,HittedTarget=HitTarget.Triple},
                    new DartShoot(){HitNumber=20,HittedTarget=HitTarget.Triple},
                    new DartShoot(){HitNumber=20,HittedTarget=HitTarget.Triple},
                    new DartShoot(){HitNumber=20,HittedTarget=HitTarget.Triple},
                    new DartShoot(){HitNumber=20,HittedTarget=HitTarget.Triple},
                    new DartShoot(){HitNumber=20,HittedTarget=HitTarget.Triple},
                    new DartShoot(){HitNumber=19,HittedTarget=HitTarget.Triple},
                    new DartShoot(){HitNumber=12,HittedTarget=HitTarget.Double}
                }
            },
....

Aus dem Dictionary hatte ich mir dann ein Zufälliges Spiel rausgesucht, und die Shoots nach und nach abgearbeitet. Was Doof ist, weil man nach einer Weile die Spielzüge kennen dürfte. Die Variante werde ich noch nehmen, um ein eigenes Spiel zu Speichern, um gegen sich selber zu spielen.

Nun habe ich eine Liste mit Nummern, und eine Liste mit HitTargets, wo ich mir zufällig eine Nummer, und ein Multipliaktor rauspicke.


List<int> HardLevelNo= new List<int>(new int[] {25,20,19,18,16,1,5,0});
List<HitTarget> HardLevelHitTargets = new List<HitTarget>() { HitTarget.Single, HitTarget.Triple, HitTarget.Double, HitTarget.Out, HitTarget.Triple, HitTarget.Triple, HitTarget.Double };

Wo ich mir dann jeweils ein ZufallWert raushole:


 public static IEnumerable<T> RandomEnumValue<T>(this IEnumerable<T> source, Random rng)
        {
            Random rnd = new Random();
            List<T> values = Enumerable.ToList(source);
            int size = values.Count - 1;
            while (true)
            {
                yield return values[rnd.Next(size)];
            }
        }

Random rand = new Random();
int randNo = RandomEnumValue(ComputerPersons.X01Extrem, rand).First();
HitTarget randHitTarget = RandomEnumValue(ComputerPersons.X01ExtremHitTargets, rand).First();
new DartShoot(randNo,randHitTarget);

Alternativ könnte man eine Liste oder Dictionary mit fertigen Würfen erstellen, und sich dann ein Zufälliges Paar heranholen:


new List<DartShoot>
{
new DartShoot(){HitNumber=20,HittedTarget=HitTarget.Single},
new DartShoot(){HitNumber=5,HittedTarget=HitTarget.Double},
new DartShoot(){HitNumber=15,HittedTarget=HitTarget.Triple},
new DartShoot(){HitNumber=20,HittedTarget=HitTarget.Double},
...

Wenn der Computer z.B. noch 40 Punkte offen hat, und zum Gewinnen eine 20 x2 braucht. ist es wahsrcheinlicher dass er: Doppel 5 trifft, Doppel 1, 0, oder Einfach 20.

Von der Abhängikeit des Punktestand soll die Wahrscheinlichkeit hervorgehen welches Ziel der Computer Treffen kann. So oder so brauche ich ja einige Listen aus den ich mir die Sachen raushole. Nun überlege ich wie ich das am besten/realistischen steuern könnte.

Wie würdet Ihr das machen? Liste Nummern, Multiplaktor separat, oder eine Paarweise Liste? Oder ganz andere herangehensweise?

Danke

18.02.2016 - 12:59 Uhr

Ja. Mal schauen was sich noch machen lässt.

Hilft auf jedenfall schonmal, ist der Code doch bisschen verständlicher geworden , zumindest klappt nun alles auf Anhieb wo ich die Tage am rummurksen war und den Überblick verloren hatte. 😁

Danke nochmal.

18.02.2016 - 09:24 Uhr

so z.B.: ?


   #region Strategy interface
    public interface IXATCStrategy
    {
        int CalculateNextNumber(int currHitNo);
        ATCGameType GameType { get; set; }
        ATCDirection Direction { get; set; }
        ATCSpeed Speed { get; set; }
        bool PlayWithBull { get; set; }
        HitTarget HittedTarget {get;set;}
    }
    #endregion


    public class NextTargetToHitStrategy
    {
        private ATCGameType _gametype;
        private ATCDirection _direction;
        private ATCSpeed _speed;
        bool _playWithBull;
        private HitTarget _hittedTarget;

        public NextTargetToHitStrategy(ATCGameType gameType, ATCDirection direction, ATCSpeed speed, bool playWithBull, HitTarget hittedTarget)
        {
            this._gametype = gameType;
            this._direction = direction;
            this._speed = speed;
            this._playWithBull = playWithBull;
            this._hittedTarget = hittedTarget;
        }

        public IXATCStrategy GetStrategory()
        {
            IXATCStrategy selectedStrategy = null;
            
            if (_direction == ATCDirection.Numerical)
            {
                if (_speed == ATCSpeed.Slow)
                {
                    selectedStrategy = new NumericalSlow();
                }
                else if (_speed == ATCSpeed.Fast)
                {
                    selectedStrategy = new NumericalFast();
                }

            }
            else if (_direction == ATCDirection.Random)
            {
                if (_speed == ATCSpeed.Slow)
                {
                    selectedStrategy = new RandomSlow();
                }
                else if (_speed == ATCSpeed.Fast)
                {
                    selectedStrategy = new RandomFast();
                }
            }
            selectedStrategy.GameType = _gametype;
            selectedStrategy.Direction = _direction;
            selectedStrategy.Speed = _speed;
            selectedStrategy.PlayWithBull = _playWithBull;
            selectedStrategy.HittedTarget = _hittedTarget;
            return selectedStrategy;
        } 

    }

    class NumericalSlow : IXATCStrategy
    {
        private List<int> list = MyDictionary.XATCSortedNumbers;
        public ATCGameType GameType { get; set; }
        public ATCDirection Direction { get; set; }
        public ATCSpeed Speed { get; set; }
        public bool PlayWithBull { get; set; }
        public HitTarget HittedTarget { get; set; }

        public int CalculateNextNumber(int currHitNo)
        {
            return 0;
        }
    }

    class NumericalFast : IXATCStrategy
    {
        private List<int> list = MyDictionary.XATCSortedNumbers;
        public ATCGameType GameType { get; set; }
        public ATCDirection Direction { get; set; }
        public ATCSpeed Speed { get; set; }
        public bool PlayWithBull { get; set; }
        public HitTarget HittedTarget { get; set; }

        public int CalculateNextNumber(int currHitNo)
        {
            return 0;
        }
    }

    class RandomSlow : IXATCStrategy
    {
        private List<int> list = MyDictionary.XATCRandomNumbers;
        public ATCGameType GameType { get; set; }
        public ATCDirection Direction { get; set; }
        public ATCSpeed Speed { get; set; }
        public bool PlayWithBull { get; set; }
        public HitTarget HittedTarget { get; set; }

        public int CalculateNextNumber(int currHitNo)
        {
            return 0;
        }
    }
    
    class RandomFast : IXATCStrategy
    {
        private List<int> list = MyDictionary.XATCRandomNumbers;
        public ATCGameType GameType { get; set; }
        public ATCDirection Direction { get; set; }
        public ATCSpeed Speed { get; set; }
        public bool PlayWithBull { get; set; }
        public HitTarget HittedTarget { get; set; }

        public int CalculateNextNumber(int currHitNo)
        {
            return 0;
        }
    }


Und der Aufruf dann so:


 IXATCStrategy nextTargetToHitStrategy = new NextTargetToHitStrategy(_gameType, _atcDirection, _atcSpeed, _playWithBull, hittarget).GetStrategory();
int strategyResult = nextTargetToHitStrategy.CalculateNextNumber(currHitNo);
System.Diagnostics.Debug.WriteLine("Strategy Result: " + strategyResult);

18.02.2016 - 07:49 Uhr
  
IGameStrategy nextTargetToHitStrategy = new NotSureAboutTheNameStrategyFactory(_atcDirection, _atcSpeed, hittarget).GetStrategy();  
return nextTargetToHitStrategy.CalculateNextNumber(currHitNo);  
  

Ich versuch das mal. Vielen Dank für das zeigen.

17.02.2016 - 14:56 Uhr

Was mir im Nachhinein noch auffällt - für verschiedene Akteure unterschiedlich schnelle oder ganz unterschiedliche Arten der Fortbewegung zu implementieren, schreit ein bisschen nach
>
. Dürfte bei der Organisation deines Codes hilfreich sein.
LaTino

Hallo Latino,

danke für den Verweis auf das Muster. So ähnlich? habe ich es versucht umzusetzen, ich habe eine Basis Klasse Game, welche die ganzen Basis Funktionen beinhaltet, Spieler hinzufügen, bearbeiten, löschen, Start / Ende, und jedes Spiel (es geht um ein Darts Spiel) hat die gleiche Vorgehensweise, es sind immer 3 Darts pro Runde. Alles was darüber hinausgeht habe ich in einer eigenen Klasse ausgegliedert:


public class ATCGame : Game<ATCUserControl>, IGameAroundTheClock
{
...
}

Hier kommen dann die Logiken der verschiedenen Spielarten rein. Wobei ein Spiel selber so Einstellbar sein kann dass es im Grunde doch wieder ein anderes Spiel ist (also wie du jetzt sagst die Fortbewegung mal langsam mal schnell)

In meinen Falle gerade: Eine einfache Zahl getroffen, geht zur nächsten Zahl auf der Dartscheibe, trifft man Doppel/Trippel darf man 2 oder 3 weiter.

Ich guck mir das nochmal an, Code verschönern und vereinfachen (und lesbarer machen) geht fast immer 😃

Danke.

17.02.2016 - 11:34 Uhr

Möchtest du, bevor du das (zweit/dritt)-nächste Item von der Liste zurückgibst feststellen, ob es überhaupt ein zweit- oder drittnächstes gibt? Wenn ja --> gib das zurück, wenn nein --> gib das letzte der Liste zurück.

Beschreibt das dein Problem?

Hallo CoffeBean,

sorry erstmal für meine Ausdrucksweise, fällt mir manchmal schwer zu Beschreiben was dass Problem ist (Ausser dass ich kommata nicht kann X()

Deine Vermutung passt. Bevor ich das zweit/dritt nächste Element von der Liste hole, soll geprüft werden ob es ein solches gibt, wenn nicht, dann letztes Item zurückgeben.

@Latino, ja ist mir aufgefallen. Hab ich extra so genannt erstmal , weil ich durcheinander kam wann ich welchen Schritt übergab.

Mir ist nun auch aufgefallen dass ich wenn item + x größer als Anzahl der Items in der Liste ist, ich das erste Item zurückgebe, hier muss ich eigentlich nur das letzte Item zurückgeben.

Ja, sorry, ist so eine Macke von mir, ich entwickel meistens drauf los, und Räume erst später den Code auf, und bennene dann die Methoden und klassen um, gucke wo ich noch was optimieren kann, füge Kommentare hinzu... ist mir denke ich klar das ein guter Programmierer (was ich nicht bin) das vorweg schon mit erledigt, und so, einige Fragen / Probleme wahrscheinlich erst gar nicht entstehen würden.

Vielen Dank für euren Denkanstoß

17.02.2016 - 10:37 Uhr

Guten Morgen,

ich habe 2 Listen:


 public static List<int> XATCSortedNumbers = new List<int>()
{
{1},
{2},
....
{19},
{20},
{25}
};

 public static List<int> XATCRandomNumbers = new List<int>()
{
{25},    
{20},
{1},
{18},
{4},
{13},
....
{9},
{12},
{5},
};

Und folgenden Helfer um dort ein passenden wert zu bekommen:


public static class Helperlein
    {
        public static T NextOf<T>(this IList<T> list, T item)
        {
            return list[(list.IndexOf(item) + 1) == list.Count ? 0 : (list.IndexOf(item) + 1)];
        }
        public static T Next2Of<T>(this IList<T> list, T item)
        {
            return list[(list.IndexOf(item) + 2) >= list.Count ? 0 : (list.IndexOf(item) + 2)];
        }
        public static T Next3Of<T>(this IList<T> list, T item)
        {
            return list[(list.IndexOf(item) + 3) >= list.Count ? 0 : (list.IndexOf(item) + 3)];
        }
    }

Und folgende Funktion welche auf den passenden Helferlein verweist:


 public int GetNextNoToHit(int currHitNo, HitTarget hittarget, XATCPerson p)
        {
            int nextNo = 0;
            if (_atcDirection == ATCDirection.Numerical)
            {
                if (_atcSpeed == ATCSpeed.Slow)
                {
                    ///Next sorted 
                    nextNo = MyDictionary.XATCSortedNumbers.NextOf(currHitNo);
                }
                else if (_atcSpeed == ATCSpeed.Fast)
                {
                    //Next sorted +2 or +3 
                    if (hittarget == HitTarget.Single)
                    {
                        nextNo = MyDictionary.XATCSortedNumbers.NextOf(currHitNo);
                    }
                    else if (hittarget == HitTarget.Double)
                    {
                        nextNo = MyDictionary.XATCSortedNumbers.Next2Of(currHitNo);
                    } 
                    else if (hittarget == HitTarget.Triple)
                    {
                        nextNo = MyDictionary.XATCSortedNumbers.Next3Of(currHitNo);
                    }
                }
                
            }
            else if (_atcDirection == ATCDirection.Random)
            {
                if (_atcSpeed == ATCSpeed.Slow)
                {
                    // Next Random Nummer 
                    nextNo = MyDictionary.XATCRandomNumbers.NextOf(currHitNo);
                }
                else if (_atcSpeed == ATCSpeed.Fast)
                {
                    //Next sorted +2 or +3 
                    if (hittarget == HitTarget.Single)
                    {
                        nextNo = MyDictionary.XATCRandomNumbers.NextOf(currHitNo);
                    }
                    if (hittarget == HitTarget.Double)
                    {
                        nextNo = MyDictionary.XATCRandomNumbers.Next2Of(currHitNo);
                    }
                    else if (hittarget == HitTarget.Triple)
                    {
                        nextNo = MyDictionary.XATCRandomNumbers.Next3Of(currHitNo);
                    }
                }
            }

            return nextNo;
        }

Ziel ist die letzte Zahl der Liste, wenn nextNo = letzte Zahl, Ziel erreicht, für NextOf passt das, da einer Schritte, stehe ich aber bei XATCSortedNumbers auf 19, und HitTarget ist Triple, bekomme ich 1 zurück.

Wie könnte ich das elegant lösen, dass wenn Next2Of oder Next3Of über das Ende hinaus gehen, ich die letzte Zahl der Liste zurückbekomme?.

ich hatte erst gedacht über IndexOf prüfen, aber damit hätte ich Probleme wenn schon beim Start weil Index von nextNo immer kleiner ist als FinalNo:


else if (hittarget == HitTarget.Triple)
                    {
                        nextNo = MyDictionary.XATCRandomNumbers.Next3Of(currHitNo);
                        if (MyDictionary.XATCRandomNumbers.IndexOf(nextNo) < MyDictionary.XATCRandomNumbers.IndexOf(GetFinalNo()))
                        {

                        }
                        
                    }

Hat jemand ein Denkanstoß für mich.? 8)

Vielen Dank

22.01.2016 - 14:02 Uhr

Interface?

Hab den Eindruck das die Lösung aller meiner Probleme meistens an fehlenden Interface liegt... 📗

 public interface IGame
    {
        ObservableCollection<Person> Persons{ get; set; }
    }

 private IGame _currGame = (IGame)GameStorage.AllGames.Gs.X01Games[_gameIndex];

 private IGame _currGame = (IGame)GameStorage.AllGames.Gs.X10020Games[_gameIndex];

Was natürlich nicht geht weil nicht gecastet werden kann und ich es erst zur Laufzeit gemerkt hab ... hehe ..

Schönes Wochenende !

21.01.2016 - 11:29 Uhr

Nein,
>
benötigst du, wenn du eine Klasse teilen möchtest (z.B. über mehrere .cs-Dateien).

Ableitungen kannst du ganz einfach ohne Schlüsselwörter anlegen:

Ja, habe das nun auch nochmal nachgelesen. Sind manchmal so Kleinigkeiten wo man denkt dass ist/muss so, und ist aber Fehlerhaft, und verursacht dadurch weitere Fehler 🙂

Mit der ObservableCollection <T> das funktioniert gut !

Nun Frage ich mich ob ich auch einen "Generischen Context" hinbekomme... Damit ich einfacher auf die Objekte zugreifen kann, welche sich in den Observable Collections befinden.

Auf ein Game greife ich derzeit wie folgt zu:

Im Falle von X01Game


// Da wo der Game Typ nicht bekannt ist , z.b auf der MakePerson.xaml Page
 
private object currGame;
currGame= GameStore.AllGames.Gs.X01Games[_gameIndex]; 

// wenn bekannt , z.B. in der Game Engine
X01Game currentGame = currGame= GameStore.AllGames.Gs.X01Games[_gameIndex]; 

Im Falle von X10020


currGame= GameStore.AllGames.Gs.X10020Games[_gameIndex]; 

Dann die Person(en).


Person currentPerson = GameStore.AllGames.Gs.X01Games[_gameIndex].Persons.ElementAt(_personIndex);

// oder 

Person currentPerson = GameStore.AllGames.Gs.X10020Games[_gameIndex].Persons.ElementAt(_personIndex);

Das ist ja so nicht wirklich "sexy" ... 🙁

Wenn ich auf der MakePerson.xaml Page ankomme, stehen mir die String Parameter "gameType" zur Verfügung ("X01Game" oder "X10020"), wo ich dann mittels Switch momentan die passenden Variablen setze(Generische XAML Page geht glaube ich nicht, sonst würde ich es wie hier machen) :


private object currGame;
private Person currentPerson;

private void SetCurrentGameAndPerson()
        {
            switch (_gameType)
            {
                case "X01Game":
                    currGame = GameStore.AllGames.Gs.X01Games[_gameIndex];
                    if (_personIndex != -1)
                        currentPerson = GameStore.AllGames.Gs.X01Games[_gameIndex].Persons.ElementAt(_personIndex);
                    else
                        currentPerson = new X01Person();
                    break;
                case "X10020":
                    currGame = GameStore.AllGames.Gs.X10020Games[_gameIndex];
                    if (_personIndex != -1)
                        currentPerson = GameStore.AllGames.Gs.X10020Games[_gameIndex].Persons.ElementAt(_personIndex);
                    else
                        currentPerson = new PersonX10020();
                    break;
                default:
                    break;
            }
        }

Wie könnte ich hier auch ein Spiel Generisch machen? Habe die Struktur mal vereinfacht zum Testen:


    public class Games
    {
        public Games() { }

        public ObservableCollection<X01Game> X01Games { get; set; }
        public ObservableCollection<X10020Game> X10020Games { get; set; }
    }


    public class Person
    {
        public string Name { get; set; }
    }
    public class PersonX01 : Person
    {
        public string X01PersonProperty { get; set; }
    }
    public class PersonX10020 : Person
    {
        public string X10020PersonProperty { get; set; }
    }
    

    public abstract class GameBase<TPerson> where TPerson : Person
    {
        public string GameStatus { get; set; }
        public string GameDuration { get; set; }
        public ObservableCollection<TPerson> Persons { get; set; }
    }

    public class X01Game : GameBase<PersonX01>
    {
        public X01Game(){}
        public string X01GameProperty { get; set; }
    }

    public class X10020Game : GameBase<PersonX10020>
    {
        public X10020Game(){}
        public string X10020GameProperty { get; set; }
    }

     public class TestGenerics
    {
        Games _games;
        public TestGenerics()
        {
            Start();
        }

        private void Start()
        {
            _games = new Games();

            _games.X01Games.Add(new X01Game { GameStatus = "finished", GameDuration = "10hrs" });
            _games.X01Games[0].Persons.Add(new PersonX01 { Name = "Peter" });
            _games.X01Games[0].Persons.Add(new PersonX01 { Name = "Paul" });

            _games.X01Games.Add(new X01Game { GameStatus = "Started", GameDuration = "1hrs" });
            _games.X01Games[1].Persons.Add(new PersonX01 { Name = "Julia" });
            _games.X01Games[1].Persons.Add(new PersonX01 { Name = "Jennifer" });


            _games.X10020Games.Add(new X10020Game { GameStatus = "started", GameDuration = "1hrs" });
            _games.X10020Games[0].Persons.Add(new PersonX10020 { Name = "Peter" });
            _games.X10020Games[0].Persons.Add(new PersonX10020 { Name = "Paul" });

            SelectAX01Game(1);
        }

        private void SelectAX01Game(int index)
        {
            X01Game x = _games.X01Games[index];
            Person p = x.Persons.ElementAt(0);

            // Wünschenswert: 
            GenericGame game = _games.X01Games[index];
            Person p = game.Persons.ElementAt(0);
        }
    }

Interface?

Danke

20.01.2016 - 14:41 Uhr

Hi,

ja Grundlagen kann man sich nicht oft genug anschauen 🙂

Partial class brauche ich doch wenn ich eine Klasse erweitere?
Also es gibt eine Person, und eine erweiterte Person (PersonX10020 ) welche die Person um Merkmale erweitert die nur im Spiel X10020 wichtig sind. (Okay ginge wahrscheinlich auch indem man der Person eine Spiel Eigenschaft anhängt oder so)

INotifyPropertyChanged brauch ich (geht wahrscheinlich auch anders...) um meine UI zu aktualisieren, nachdem dies oder das passiert.

MyGames benötige ich aus diversen Gründen um die Klasse Serialisiert zu speichern, ich starte die App, MyGames wird initialisiert, und dann erst werden bei Bedarf Daten aus dem IsolatedStorage geladen.

Ich versuchs mal mit Generics. Hatte jetzt ein "Workaround" aber nicht Typsicher.

Danke für deine Hilfe 👍

20.01.2016 - 12:37 Uhr

Hi,

ja, sorry, ich versuchs nochmal genauer.

Also ist eine Win Phone App, die Exception kommt bei :


public partial class App : Application
{

      private void Application_Launching(object sender, LaunchingEventArgs e)
      {
          LoadGamesList();
      }

     private void Application_UnhandledException(object sender,  ApplicationUnhandledExceptionEventArgs e)
     {
           string errorString = "Message: " + e.ExceptionObject.Message + "Stack Trace: " + e.ExceptionObject.StackTrace;
     }

}

Klassen:


public class GameStore : INotifyPropertyChanged
{
     public static MyGames AllGames 
        { 
            get
            {
                if (gamesList == null)
                    gamesList = new MyGames();
                return gamesList;
            }
        }
}

public class MyGames : INotifyPropertyChanged
{
     private Games _g = null;        

     public Games Gs
        {
            get
            {
                if (_g == null)
                    _g = new Games();
                return _g;
            }
}

public class Games : INotifyPropertyChanged
{
   public ObservableCollection<X01Game> X01Games{}
   public ObservableCollection<X10020> X10020Games{}
}

public partial class XGame : INotifyPropertyChanged
{
    [DataMember]
     public ObservableCollection<Person> Persons{}
}

public partial class X10020 : XGame, INotifyPropertyChanged
{
    [DataMember]
     public ObservableCollection<PersonX10020> Persons
}

public partial class X01Game : XGame, INotifyPropertyChanged
{
     [DataMember]
     public ObservableCollection<X01Person> Persons{}
}

public class Person : INotifyPropertyChanged
{
}
public partial class X01Person : Person
{
}
public partial class PersonX10020 : Person
{
}


Demo:


 X10020 demogame = new X10020();
demogame.Name = "Demo";

PersonX10020 person1 = new PersonX10020()
{
  Name = "Peter ",
  Gender = "male",
};

GameStore.AllGames.Gs.X10020Games.Add(demogame);
demogame.Persons.Add(person1);

Auf der Seite wo ich binde :


protected override void OnNavigatedTo(NavigationEventArgs e)
{
   currGame = GameStore.AllGames.Gs.X10020Games[_gameIndex];
   this.DataContext = currGame;
}

Nehme ich this.DataContext = currGame; raus kommt der Fehler nicht. Die Persons Liste ist gefüllt.

Ich hatte bei der Anwendung bisher nur eine Klasse Spiel welche eine Persons Liste hatte, war alles gut, nun möchte ich mehrere Spiele mit jeweils einer Personen Liste implementieren. Wenn die Struktur der Klassen so okay ist, dann kann es eigentlich nur sein dass sich irgendwo beim binden noch auf eine "alte" Person Liste zugegriffen wird.

Ambigous heißt ja so viel wie irgendwas ist mehrdeutig.

Hmm Okay. Der Fehler ist weg wenn ich ein [DataMember] weg nehme, 2 x DataMember Persons scheint also Ambigous...

Ich überprüf nochmal die Datenstruktur.... 😁

20.01.2016 - 10:26 Uhr

An welcher Stelle wird die Exception denn ausgelöst?

Hi,

scheint mir so als würde die Exception ausgelöst beim Zugriff auf die ObservableCollection<PersonX10020>


public class MyXGames
{
        public ObservableCollection<X01Game> X01GameList{}
        public ObservableCollection<X10020Game>X10020GameList{}

public class XGame 
{
        public ObservableCollection<Person> Persons{}
}
public class X01Person :Person{}
public class X10020Person :Person{}

public class X01Game :XGame
{
         public ObservableCollection<PersonX01> Persons{}
}

public class X10020Game :XGame
{
         public ObservableCollection<PersonX10020> Persons{}
}

Zu Testzwecken:


 X10020 demogame = new X10020();
demogame.Name = "Demo";
PersonX10020 person1 = new PersonX10020()
{
   Name = "Peter",
   Gender = "male",
};

AllGames.X10020Games.Add(demogame);
demogame.Persons.Add(person1);

demogame.Persons ist an eine ListBox gebunden

Beim Zugriff auf die Seite wo die ListBox ist, ist demogame.Persons leer.

Scheint sich ins Gehege zu kommen mit XGame.Persons?

Benenne ich XGame.Persons um, ist demogame.Persons leer, mit XGame.Persons, ist demogame.Persons gefüllt, aber es kommt der Fehler.

Danke

20.01.2016 - 09:48 Uhr

"Klappt irgendwie nicht" ist keine Fehlermeldung. Ich vermute mal, dir würde ein
>
helfen.
LaTino

Hi,

ja, "irgendwie nicht" ist keine Fehlermeldung , stimmt schon...

habe nun was konkreteres:

Fehlermeldung:
Unhandled Error
Ambiguous match found.Stack Trace: at System.RuntimeType.GetPropertyImpl(String name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers)

at System.Type.GetProperty(String name)
at System.Windows.PropertyAccessPathStep.ConnectToPropertyInSource(Boolean isSourceCollectionViewCurrentItem)
at System.Windows.PropertyAccessPathStep.ConnectToProperty()
at System.Windows.PropertyAccessPathStep.ReConnect(Object newSource)
at System.Windows.PropertyPathListener.ReConnect(Object source)
at System.Windows.Data.BindingExpression.SourceAcquired()
at System.Windows.Data.BindingExpression.System.Windows.IDataContextChangedListener.OnDataContextChanged(Object sender, DataContextChangedEventArgs e)
at System.Windows.Data.BindingExpression.DataContextChanged(Object sender, DataContextChangedEventArgs e)
at System.Windows.FrameworkElement.OnDataContextChanged(DataContextChangedEventArgs e)
at System.Windows.FrameworkElement.OnAncestorDataContextChanged(DataContextChangedEventArgs e)
at System.Windows.FrameworkElement.NotifyDataContextChanged(DataContextChangedEventArgs e)
at System.Windows.FrameworkElement.OnAncestorDataContextChanged(DataContextChangedEventArgs e)
at System.Windows.FrameworkElement.NotifyDataContextChanged(DataContextChangedEventArgs e)
at System.Windows.FrameworkElement.OnTreeParentUpdated(DependencyObject newParent, Boolean bIsNewParentAlive)
at System.Windows.DependencyObject.UpdateTreeParent(IManagedPeer oldParent, IManagedPeer newParent, Boolean bIsNewParentAlive, Boolean keepReferenceToParent)
at MS.Internal.FrameworkCallbacks.ManagedPeerTreeUpdate(IntPtr oldParentElement, IntPtr parentElement, IntPtr childElement, Byte bIsParentAlive, Byte bKeepReferenceToParent, Byte bCanCreateParent)

Scheint sich also irgendwas zu "überschneiden"

20.01.2016 - 09:04 Uhr

Hi,

ich habe folgende Klassen:


public class MyXGames
{
        public ObservableCollection<X01Game> X01GameList{}
        public ObservableCollection<X10020Game>X10020GameList{}

public class XGame {}
public class X01Person :Person{}
public class X10020Person :Person{}

public class X01Game :XGame
{
         public ObservableCollection<PersonX01> Persons{}
}

public class X10020Game :XGame
{
         public ObservableCollection<PersonX10020> Persons{}
}


Nun habe ich ein Formular (XAML) welches an eine "Person" gebunden war.
Dieses Form(Eingabemöglichkeit) möchte ich nun "Spielübergreifend" nutzen.

beim Aufruf von dem Form , ich nenne es mal MakePerson, steht mir folgendes zur verfügung:

private int _gameIndex;
private string _gameType;
private int _personIndex;

_gametype stellt den Spieltyp da: X01Game oder X10020Game,

_personindex stellt den index der Person in der Liste Persons da (ggf. -1 wenn eine neue Person erstellt werden muss),

gameIndex stellt den Index des Game in der Liste X01GameList oder X10020GameList da.

Wie kann ich hier gewährleisten dass der richtige Spieler dem richtigen Spiel zugeordnet wird?


public class MakepersonForm
{
   private int _gameIndex;
   private string _gameType;
   private int _personIndex;

   private Person currentPerson;
   private XGame currentGame;

   protected override void OnNavigatedTo(NavigationEventArgs e)
   {
        _gameIndex = int.Parse(NavigationContext.QueryString["index"]);
        _personIndex = int.Parse(NavigationContext.QueryString["pId"]);
        _gameType = NavigationContext.QueryString["gt"];

        SetCurrentGameAndPerson();
   }

}

Ich hab da an folgdendes Gedacht:


private void SetCurrentGameAndPerson()
        {
            switch (_gameType)
            {
                case "X01Game":
                    currGame = AllGames.X01Games[_gameIndex];
                    //currentPerson = currGame.Persons.ElementAt(_personIndex);
                    break;
                case "X10020":
                    currGame = AllGames.X10020Games[_gameIndex];
                    //currentPerson = currGame.Persons.ElementAt(_personIndex);
                    break;
                default:
                    break;
            }
        }

Klappt aber irgendwie nicht, bin zwar schon am Debuggen, aber sehe nicht so recht was das Problem ist, läuft aber was krum mit den Indexes

Versteht Ihr was ich meine? Wie könnte ich das lösen?

Danke

06.01.2016 - 09:16 Uhr

Hi,

VS2013, Windows Phone 8

ich habe eine ObservableCollection<Person>:


public ObservableCollection<Person> Persons
        {
            get
            {
                if (_persons == null)
                {
                    _persons = new ObservableCollection<Person>();
                }
                return _persons;
            }
            set
            {
                if (_persons != value)
                {
                    _persons = value;
                    NotifyPropertyChanged("Persons");
                }
            }
        }

die Collection ist an einer ListBox Gebunden. Nun Versuche ich die Elemente in der Liste zu verschieben. Ich dachte eigentlich folgendes würde gehen:


Persons.Move(oldIndex,newIndex);

Damit bekomme ich aber den Fehler "Not Supported Exception"> Fehlermeldung:

In System.NotSupportedException ist eine Ausnahme vom Typ "System.Windows.ni.dll" aufgetreten, doch wurde diese im Benutzercode nicht verarbeitet.

Zusätzliche Informationen: Unexpected collection change action 'Move'.

Folgendermaßen geht es :


Persons.RemoveAt(oldindex);
Persons.Insert(newIndex, person);

Warum geht Move hier nicht?

Danke

23.12.2015 - 14:47 Uhr

Du hast den Converter von dort übernommen? Sprich Namespace etc. passen?

Ja, habe mir auch sogar schon beispiel Code runtergeladen von WP 8.1 Converter , gleiche Problem mit den Namespace, nun habe ich gelesen das es evtl. auch an VS Community 2015 liegen könnte.

Aber ist mir zu Hoch, ich Update die App mit WP 8.0 weiter, und sobald ich ein WP10 gerät habe versuche ich mich dann mal an Universal Apps.

Habe ein PC mit Win 10, (Ohne Hardware Virtualisation), VS Community 2015, und VS Studio 2013, mit VS 2015 habe ich viele Probleme irgendwie, wie z.B. Errors die angezeigt werden, nach Schließen öffnen ders Projekt weg sind... in VS 2013 aber kann ich keine UAP programmieren... muss mal meine ENtwicklungsumgebungen neu aufsetzen und mal neue Hardware besorgen 😃

23.12.2015 - 11:14 Uhr

Hi,

ich versuche gerade eine WP8.0 App auf Windows Phone 8.1 zu migrieren (würde auf Universal App gehen aber habe nur ein WP8.1) .

Ich versuche bestimmte Werte zu konvertieren, so wie es in dem Beispiel hier steht:

IValueConverter interface

Es kommt immer der Fehler bei <local:DateFormatter x:Key="FormatConverter" />> Fehlermeldung:

Der Name DateFormatter ist im namespace using:ConverterParameterEx nicht vorhanden

Diesbezüglich habe ich folgendes probiert: die Converter in eine eigene Library gepackt mit Target Any CPU, Visual Studio Community 2015 geschlossen, neu gestartet, bin/obj Ordner gelöscht , mehr habe ich im www nicht finden können, und weiß grad nicht weiter.

Hat von euch jemand eine Idee?

Danke

03.11.2015 - 17:25 Uhr

Hi,

also ich versuch mal zu Beschreiben was ich mache.

Ich habe ein Projekt Models , dort sind einfache Objekte , diese Objekte /Klasse dienen mir als CodeFirst um Änderungen in der SQL DB zu machen. Also z.B. Klasse Car


public partial class Car : IBaseModel
    {
        public Car()
        {
            
        }

        [MaxLength(50)]
        [Key]
        public string CaryCode { get; set; }
        public string CarName { get; set; }
    }

Dann habe ich ein Projekt DataTier, dort befinden sich die EF Migrationen, Repositories, UnitOfWork


 public interface ICarRepository : IRepository<Car>
    {
    }

    public class CarRepository : Repository<Car>, ICarRepository
    {
        public CarRepository(IUnitOfWork unitOfWork)
            : base(unitOfWork)
        {


        }

        public IQueryable<Car> GetAllCars()
        {
            return this.GetAll();
        }
    }

Dann habe ich ein Projekt BusinnesLogic,


public class CarManager : ICarManager
    {
        private IUnitOfWork _unitOfWork;
        private CarRepository _carRepository;

        public CarManager()
        {
            this._unitOfWork = new UnitOfWork(new MyDBContext());
            this._carRepository = new CarRepository(_unitOfWork);

        }

        public IList<Car> GetAllCars()
        {
            return _carRepository.GetAllCars().ToList();
        }
}

Dann habe ich ein Projekt Interfaces, wo ich ein Interface zum Service und ein Interface zum CarManager drin habe.


 public interface ICarService
    {
        void CreateCar(Car car);
        void DeleteCar(Car car);
        void UpdateCar(Car car);
        IList<Car> GetAllCars();

        event Action<Car> UpdateCarData;
    }

    public interface ICarManager
    {
        void CreateCar(Car car);
        void DeleteCar(Car car);
        void UpdateCar(Car car);
        IList<Car> GetAllCars();
    }

Dann habe ich ein Projekt Service


public class CarService : ICarService, ICarManager
    {
}

Dann habe ich noch ein Projekt Service Access , welches den Zugriff auf den CarService bahandelt,...

Und die GUI ...

Wenn ich nun in der GUI eine Liste von Cars brauche, welche ich mit


public async Task<IList<Car>> GetAllCars()
        {
            var objectList = await Task.Run(() => CarServiceProxy.GetAllCars());
            return objectList;
        }

holen würde. Muss ich ja erst alle anderen Sachen erstellen/zur Verfügung stellen, also Repository, Businness Logic, Service Access, Service... bevor ich Cars in der GUI zur verwenden kann. Ist halt bissl Copy/Paste und Objektname / methoden umbennenen ...

Mit Basis Struktur meinte ich alle verfügungen über Basis Operationen CRUD, wird dann um individuelle Logik erweitert.

Also ich suche einen Weg um das abzukürzen, ich geh momentan hin und erstelle mir eine neue Klasse cars.cs, dann Migration zur DB, dann Repository erstellen, Interfaces erstellen, Businness Layer, Service erstellen, .... Schritte sind immer gleich obs nun Car oder House ist.

Wie würde man das üblicherweise machen?

EDIT: Danke Zelle, dann versuch ich mal damit , Template/Vorlage ist klar , wusste aber nicht genau welche Templates, oder ob VS 2015 da ab haus was anbietet. Ich versuch mal mich da durch zu wusseln.

Danke

03.11.2015 - 15:42 Uhr

Hi,

ich hab eine relativ große Anwendung verteilt auf mehrere Projekte, nun ist es mittlerweile recht mühsam wenn ich eine Klasse / Objekt anlegen möchte. Da sich die Basis Struktur überall wiederholt, möchte ich mit einer Vorlage die passenden Dateien samt klassen/Interfaces erstellen.

Ich hatte mal irgendwo gesehen , nannte sich glaube ich ReverseEngineerCodeFirst, wo anhand einer DB Code Dateien für Context, mapping etc generiert wurden mit T4 ? Templates.

Was sind die richtigen Stichpunkte um solche Vorlagen zu erstellen? Project Templates?

Also ich möchte den Namen der Klasse angeben und dann soll automatisch dies/das jenes an Code generiert werden, wo der Name übernommen wird, und hier/da neue Dateien.cs für angelegt werden, die ich später dann mit individueller Logik erweitern kann.

Arbeite aktuell mit VS 2015 Community, wie kann ich dass umsetzen, bzw. wo finde ich den Einstieg.

Vielen Dank

22.10.2015 - 14:53 Uhr

hmm. Okay...

Dann halt auf "herkömmlichen Wege" :


string ean = row["columnname"].ToString();

statt


string ean = row.Field<string>("columnname");

Dachte ich könnte mal was neues ausprobieren 😃

Danke

22.10.2015 - 12:15 Uhr

Hallo,

danke für die Antwort.

Verstehe ich aber nicht ganz.


foreach (DataRow row in dataset.Tables[sheetName].Rows)
{
    var typ = row[comboBoxEAN.SelectedItem.ToString()].GetType()
    .
    .
    .
   string Ean = row.Field<string>(comboBoxEAN.SelectedItem.ToString());
}

So bekomme ich den Typ. Klar.

Aber hier:

   string Ean = row.Field<string>(comboBoxEAN.SelectedItem.ToString());

hätte ich ja wieder das Problem das wenn der Wert in der Zelle ein Double ist , nicht gecastet werden kann.

Würde mir folgendes wünschen:


var typ = row["columnname"].GetType()
var x = row.Field<typ>("columname");
string Ean = CastXtoString

wünschen.

Danke

22.10.2015 - 10:50 Uhr

verwendetes Datenbanksystem: Excel /DataSet, .Net 4.5

Hi,

ich lese eine Excel Datei in meine Anwendung ein und stelle diese in einem DatagridView da:

 
reader = ExcelReaderFactory.CreateOpenXmlReader(stream);

dataSet = reader.AsDataSet();

dgV.DataSource = dataSet; 

Anschließend weise ich Werte zu in dem ich eine bestimmte Zelle anspreche:


 foreach (DataRow row in dataset.Tables[sheetName].Rows)
{
string Ean = row.Field<string>(comboBoxEAN.SelectedItem.ToString());
}

Das funktioniert solange row.Field ein String Wert beinhaltet, ist es ein double kann nicht gecastet werden. Ich müsste also erstmal den Typ herausfinden um welchen es sich handelt, um dementsprechend zu casten.

Typen würde ich wie folgt erhalten:


foreach (DataRow row in dataset.Tables[sheetName].Rows)
{
  foreach (var value in row.ItemArray)
  {
    Console.WriteLine("Spalte: {0}", value.GetType());
  }
}

Für jede Zeile wird mir hier für jede Zelle/Spalte der Typ angezeigt.

Nun hat die eingelesene Excel tabelle ca 30 Spalten, wo ich aber nur 10 von verwenden möchte, welche Spalte zugeordnet wird , wird über eine ComboBox geregelt.

Bringt mir also nichts wenn ich mit foreach durchgehe, weil ich den Typ einer bestimmten Zelle brauche.

Ich möchte also den Wert einer Zelle anhand des Spaltennamen zuweisen, muss aber vorher wissen um was für ein Typ es sich bei dem Wert handelt.

Wie könnte ich das realisieren?

Danke

17.08.2015 - 10:12 Uhr

Morgen zusammen,

ich versuche eine Win 8.1 App zu migrieren, bzw. eine Win10 UWA App draus zu machen.

Bin nun auf das Problem gestoßen dass in der UWA App der rechtsklick auf einem Button im ListView nicht funktioniert, und weiß nicht ob es nicht geht weil neue Richtlinien oder ob ich was vergessen haben könnte:

Ich hab ein ListView Element welches mir eine Liste von "Ordner" anzeigt, klickt man auf einem Ordner erscheinen Thumbnails von den Bildern die dieser ordner enthält.


<ListView HorizontalAlignment="Left"
              Margin="10,10,0,0"
              VerticalAlignment="Top"
              ItemsSource="{Binding Folders}"
              SelectionMode="Single"
              SelectedItem="{Binding SelectedFolder,Mode=TwoWay}">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <Button Command="{Binding Command}"
                  CommandParameter="{Binding}"
                  Template="{x:Null}">
                        <TextBlock Text="{Binding Name}"
                       Style="{StaticResource SubheaderTextStyle}"
                       Margin="0,0,0,3" />
                    </Button>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>

Ich arbeite mit einem Dictionary für die Commands :
this._commands = new Dictionary<int, ICommand>()

Und es gibt ein Command "FolderInvoked", welcher bei Linksklick auf dem Button in der ListView auch ausgeführt wird. (FolderInvoked durchsucht das Verzeichnis nach Bildern und zeigt diesem in einem weiteren Control als Thumbnails an)

Nun war es bei Win 8.1 App so , wenn ich rechtsklick machte auf den Button in der ListView, wurde dieser "markiert" mit einem Häkchen versehen. Dieses Verhalten ist jetzt nicht mehr. Vorher war Linksklick = Comando ausführen, Rechtsklick, Ordner markieren.

Nehme ich den Button ganz raus, wird bei der WP 8.1 der ListView eintrag markiert, mit links klick, und auch mit rechtsklick der Maus.

Nehme ich den Button bei der UWA Win 10 App raus, dann wird der ListView Eintrag nur markiert bei Maus Links klick, bei rechtsklick passiert gar nichts

Jemand eine Idee?

Danke

11.06.2015 - 13:00 Uhr

LA PACIÈNCIA ÉS LA MARE DE LA CIÈNCIA.... sagte mir irgendein Lehrer mal immer, und heißt so viel wie: Geduld ist die Mutter der Wissenschaft ...

Letztendlich doch ne Sicherheitsgeschichte...

Statt :


System.Net.CredentialCache myCredentials = new System.Net.CredentialCache();
NetworkCredential netCred = new NetworkCredential(Login, Password, Domain);
myCredentials.Add(new Uri(WebServiceURL), "NTLM", netCred);
request.UseDefaultCredentials = true;
request.Credentials = myCredentials;

nun


request.UseDefaultCredentials = true;
System.Net.ICredentials netCred = new System.Net.NetworkCredential(Login, Password, Domain);
            request.Credentials = netCred;

Und schon läuft das ganze...

😁 happy

11.06.2015 - 08:52 Uhr

Hi,

habe jetzt mal eine DLL erstellt und im SQL Eingebunden, auf Basis vom http://www.webservicex.net/CurrencyConvertor.asmx. Funktioniert .

Habe dann mal auf die DLL in ein anderen Projekt verwiesen. Und einfach aufgerufen:

HelloWorldClass.HelloWorldSP("name", "string2");

Funktioniert auch.

Demnach stimmt entweder irgendwas an den Rechten mit dem SQL nicht, oder der SQL kommt nicht klar mit der "nicht standard" Response vom NAV Webservice, oder der Request wird falsch gesendet...

Wie kann man so etwas Debuggen? Momentan sieht das Debuggen bei mir so aus: im VS ändere ich Code, gehe auf Projekt veröffentlichen, auf dem SQL Server wird die Assembly hinzugefügt und die Storage Procedur erstellt, anschließend führe ich ein SQL Script EXEC meineSP aus, welcher mir dann den (ein) Server Error 500 liefert (Fällt unterschiedlich aus, je nach Request, daher meine hoffentlich Vermutung dass die Request XML nicht richtig zusammengesetzt wird), im Ereignisprotokoll dann genauer gucken was der Fehler sagt...

Das veröffentlichen auf den SQL Server, registrieren/ändern der dll, dauert ca. 1 Minute... also mühsam sich auf diese weise dem Fehler zu nähern.

10.06.2015 - 16:50 Uhr

Hi,

weil so wie es aussieht eine dynamische Serialisierung nicht möglich ist, müsste man die Dateien ausserhalb vom VS mit der Console erstellen und bräuchte noch eine Serialisierungs.dll?

Ich versuche dass hier umzusetzen, erklärt es wohl besser als ich 🙂

Der SQL 2008 und auch der WebService Server laufen auf ein Systemin einer VM, sind aber auch im Netzwerk erreichbar, der Test über soapUI funktioniert auch ausserhalb der VM. Und das ConsoleApp Programm auch. Demnach vermute ich das alle rechtlichen belange erfüllt sind.

Kann auch sein das die Reponse vom NAV WebService "nicht sauber" ist, dass ist eigentlich generell der Fall..., aber verstehe dann nicht warum die ConsoleApp nicht meckert, aber über die DLL schon.

Aber neee, er meckert ja dass der input fehlt , demnach falscher Request abgesetzt... Ich versuch nun nochmal das ganze Body gedöns in einer Zeile unterzubringen, evtl. irgendwelche LF, versteckte zeichen etc... wobei es mit der Console App , gleicher code ja tut ... 🤔 🤔

10.06.2015 - 15:45 Uhr

VS 2012 Prof.
SQL 2008,
Net 2.0

Hi,

ich versuche gerade eine DLL zu schreiben, für den Sql 2008 Server. bekomme aber vom WebService ständig einen Error 500 zurück. Und weiß nicht wie ich das debuggen soll.

Folgendes möchte ich machen:


static string ObjectType = "Codeunit";
        static int ObjectID = 50013;
        static string Login = "MYUSER";
        static string Password = "12345";
        static string Domain = "DUMAIN";
        static string WebServiceURL = @"http://xxxx.local:7047/DynamicsNAV/WS/Company/Codeunit/RunObject";
        
        static void Main(string[] args)
        {
            string Body = @"<soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:run=""urn:microsoft-dynamics-schemas/codeunit/RunObject"">" +
                 "<soapenv:Header/><soapenv:Body><run:RunJob>" +
                             "<run:objectType>" + ObjectType + "</run:objectType>" +
                             "<run:objectID>" + ObjectID + "</run:objectID>" +
                         "</run:RunJob></soapenv:Body></soapenv:Envelope>";
            WebRequest request = HttpWebRequest.Create(WebServiceURL);
            request.Headers.Add("SOAPAction", @"urn:microsoft-dynamics-schemas/Codeunit/RunObject:RunJob");
            request.ContentType = @"application/xml; charset=utf-8";
            request.ContentLength = Body.Length;
            request.Method = "POST";

            System.Net.CredentialCache myCredentials = new System.Net.CredentialCache();
            NetworkCredential netCred = new NetworkCredential(Login, Password, Domain);
            myCredentials.Add(new Uri(WebServiceURL), "NTLM", netCred);
            request.Credentials = myCredentials;
            //request.Credentials = netCred;
            request.UseDefaultCredentials = true;
            Stream strWrite = request.GetRequestStream();
            StreamWriter sw = new StreamWriter(strWrite);
            //StreamWriter sw = new StreamWriter(@"c:\temp\ws.xml");
            sw.Write(Body.ToString());
            sw.Close();

            WebResponse wr = request.GetResponse();

            Stream s = wr.GetResponseStream();
            StreamReader sr = new StreamReader(s);
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(sr);


            if (xmlDoc.FirstChild.FirstChild.FirstChild.FirstChild.FirstChild.Value != "SUCCESS")
            {
                throw new Exception("ObjectType " + ObjectType + " ObjectID " + ObjectID.ToString() + " failed with Error: "
                    + xmlDoc.FirstChild.FirstChild.FirstChild.FirstChild.FirstChild.Value);
            }
        }

Führe ich dass genau so als Console App aus, funktioniert es einwandfrei. Ich bekomme ein result. Um zu Schauen was gesendet wird, habe ich mal die XML erstellen lassen:


<?xml version="1.0"?>
<soapenv:Envelope xmlns:run="urn:microsoft-dynamics-schemas/codeunit/RunObject" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<run:RunJob>
<run:objectType>Codeunit</run:objectType>
<run:objectID>50017</run:objectID>
</run:RunJob>
</soapenv:Body>
</soapenv:Envelope>

Mit soapUI schicke ich dieses XML an den Webservice und bekomme auch die Response:


<Soap:Envelope xmlns:Soap="http://schemas.xmlsoap.org/soap/envelope/">
   <Soap:Body>
      <RunJob_Result xmlns="urn:microsoft-dynamics-schemas/codeunit/RunObject">
         <return_value>SUCCESS</return_value>
      </RunJob_Result>
   </Soap:Body>
</Soap:Envelope>

Erstelle ich eine DLL für den SQL:


[Microsoft.SqlServer.Server.SqlProcedure]
        public static void PKAJobScheduler(string ObjectType, int ObjectID, string Login, string Password, string Domain, string WebServiceURL)
        {
// Script siehe oben 
}

komme ich nur bis

WebResponse wr = request.GetResponse();

Und finde anschließend im Ereignisprotokoll: > Fehlermeldung:

Type: System.ArgumentNullException
Message:
Der Wert darf nicht NULL sein.
Parametername: input
ParamName: input

Den gleichen Fehler bekomme ich wenn ich beim testen mit soapUI den XML Request weglasse.

Aber wenn es doch mit der Console App funktioniert, warum nicht über die Storage Procedure dll?

Also ich erstelle die DLL, von Visual Studio aus sage ich veröffentlichen, die DLL wird automatisch am SQL Server 2008 erzeugt, und auch automatisch die SP .

Die SP wird auch ausgeführt, kommentiere ich z.B. ab GetReponse alles aus, und lasse den XML Request in eine datei auf den Sql Server schreiben, wird das auch durchgeführt. Also Verbindung, und Rechte ... sollte alles okay sein.

Soweit ich weiß können die CLR Prozeduren nur Integer, null, oder void zurückgeben.
Ob es damit irgendwie zusammen hängt? Wobei die Methode ja void ist .

Also die Sp scheint ein falschen request abzusetzen, und bekommt deswegen kein response zurück. Aber warum? Wenn der gleiche Code als Console App funktioniert ?

Selbst wenn die Parameter hart rein schreibe, und nicht an die Sp übergebe, gleicher Fehler.

Was könnte da anders sein? Irgendwelche Tipps?

Danke

03.06.2015 - 13:28 Uhr

Hi,

danke für eure Antworten. 👍

Nun kann man sich via MEF alle Implementierungen einer Schnittstelle (z.B. INode) holen, die Metadaten auswerten und so die zu einem Node passende Implementierung ermitteln.

MEF hatte ich mal gehört, wusste nicht genau was man damit anstellt, habe hier ein ganz Verständlichen Einstieg gefunden.

Finde ich interessant, vielleicht nehme ich damit doch wieder meine UrsprungsIdee Plugins mit ins Boot.

Ich hab mein problem nun auch mit dem MEF gelöst. Irgendwie ne tolle Sache 🙂


public interface INodeContract
{
    void Show();
}

public interface INodeMetadata
{
    [DefaultValue("NoName")]
    string Name { get; }
}

[MetadataAttribute]
public class NodeMetadataAttribute : Attribute
{
    public string Name { get; set; }
}

[NodeMetadata(Name = "Project"]
[Export(typeof(INodeContract))]
public partial class ProjectForm : MyGenericForm<Project>, INodeContract, IHasSpecialMethod
}
[NodeMetadata(Name = "Country"]
[Export(typeof(INodeContract))]
public partial class CountryForm : MyGenericForm<Country>, INodeContract, IHasSpecialMethod
}

public partial class MyGenericForm<T> : Form, INodeContract, IHasSpecialMethod where T : new()
{
    InitializeComponent();    
    System.Diagnostics.Debug.WriteLine(" T in MyGenericForm is : " + typeof(T));
}

Im TreeNode Click dann so was wie:


[ImportMany(typeof(INodeContract))]
private IEnumerable<Lazy<INodeContract, INodeMetadata>> MyNodes{ get; set; }

void OpenOrActivateForm(string objectMetaName)
{
    var container = new CompositionContainer(catalog);
    container.ComposeParts(this);

    var formList = from x in MyNodes
                              let metadata = x.Metadata
                              where metadata.Name == objectName
                              select x.Value;

    foreach (INodeContract nc in formList )
    {
        nc.Show();
    }
}

Ausbaufähig, aber denke kann ich was mit anfangen.

Vielen Dank nochmal.

02.06.2015 - 10:25 Uhr

Hi Christian,

okay, ist ein Gefrickel, dem stimme ich irgendwo zu, sonst hätte ich wohl schon was ich möchte...

ich hab nun den gestrigen Tag damit verbracht zu suchen wie es andere wohl machen würde, entweder suche ich falsch, oder ich habe eine falsche Vorstellung wie es umgesetzt werden müsste bzw. könnte.

Über Reflection aber bin ich immer und immer wieder gestolpert.

Ich versuche nochmal die Anforderung zu spezifizieren, evtl. kann ich einen anderen Weg einschlagen.

In der Datenbank gibt es eine Tabelle TreeNodes, welche die Knoten für den TreeView speichert.
Ich habe ein Object MyNode, es wird eine Liste von myNodes eingelesen, und der TreeView anhand derer erstellt, wobei

TreeView.Node.Tag = MyNode ist

MyNode soll irgendeine Eigenschaft besitzten anhand derer ich ein bestimmtes Form identifizieren kann, so dass das Form beim MausKlick auf den TreeView Node instanziiert /aufgerufen, irgendwas mit gemacht wird.

Jetzt habe ich ein Form erstellt welches BasisFunktionen enthält für die Behandlung diverser Objekte, eine Liste von Objekten wird in einer BindingList eingelesen, und in einem DGV angezeigt, mögliche Funktionen sind: CRUD , so wie Übergabe von Feld Inhalten/Texte in eine Status Anzeige...

Die Funktionen sind für alle Objekte gleich, der Unterschied liegt immer nur im Objekt. Deswegen kam ich auf die Idee ein MyGenricForm<T> zu erstellen, wo T mein zu behandelnes Objekt sein soll.

Evtl. ist dass auch nicht der richtige Weg, und es würde reichen wenn ich ein normales Form habe, wo ich ein Object übergebe statt das Form mit ein unbekannten Typ initialisiere (ähnlich hier (aber auch mit Reflection) .

Weitere suche ergab auch "winform via object factory" (auch mit reflection)

Was die Schichten Trennung angeht, so denke ich, habe ich meine Schichten/Daten Sauber getrennt. Aufbau ist bei mir derzeit:

Client (GUi, SharedBL, ServiceAccess)
Server/Service (BL, UOW, EF)
Sql DB

Also, ich seh irgendwie kein Weg der an Reflection vorbeigeht, bevor ich nun weiter versuche würde ich aber gerne ein Gedankenstoß bekommen der in einer andere Richtung geht. Evtl. auch ein Hinweis/Verweis wie andere so etwas gelöst haben.

Danke

gruß
Peter

29.05.2015 - 18:27 Uhr

hi Christian,

also der Ablauf ist wie folgt:

Am Anfang ist der TreeList leer, der Benutzer kann sich neue Nodes anlegen, beim anlegen eines Nodes, kann der Benutzer ein Name wählen, und aus einer DropDown Box ein WinForm. In Dieser DropDown Box wurden alle vorhandenen Formulare gelistet welche von MyForms geerbt hatten.

Gespeichert wurde dann der Name der Form.


private static List<string> GetFormsInCurrentAssemly()
        {
            List<string> formList = new List<string>(new string[] { "" });
            // Current Assembly
            Console.WriteLine("========== Forms in Current Assembly ===================================");
            Assembly SampleAssembly = Assembly.GetExecutingAssembly();
            System.Type[] ts = SampleAssembly.GetTypes();
            string text = "";
            for (int i = 0; i < ts.Length; i++)
            {
                if (ts[i].IsSubclassOf(typeof(MyForm)) || (ts[i]).GetType() == typeof(MyForm))
                {
                    formList.Add(ts[i].FullName);
                }
            }
            return formList;
        }

Das hat ganz gut funktioniert, ich hatte viele Forms:


public class ProjectForm:MyForm{}
public class CountryForm:MyForm{}
public class IgrendwasForm:MyForm{}
...

Mit Click auf ein Node:


System.Diagnostics.Debug.WriteLine("Node Mouse Click ");
Node node = (Node)(e.Node.Tag);
if ((node.Form != null) && (e.Node.GetNodeCount(true) == 0))
{
this.BeginInvoke(new Action(() => openOrActivateForm(node.Form))); //Node.Form is string
}

Also ich hab in der Datenbank Nodes gespeichert, die Liste lese ich ein, und erstelle anhand derer ein TreeView.

Da alle Forms das gleiche machen, aber nur Unterschiedliche Objekte behandeln, habe ich diese nun reduziert auf ein MyGenericForm<T>.

Der Benutzer soll halt frei wählen können welches Form er mit dem Click auf den Node öffnen kann. Und diese Angabe soll in der DB gespeichert werden.

Aber ich weiß halt nicht wie ich nun das MyGenericsForm<T> initialisiere bzw. öffne, weil T ist ja nicht bekannt, ich habe nur T als string vorliegen.

29.05.2015 - 17:31 Uhr

Hi Christian,

die Anforderung ist:

Ich hab eine TreeNode Liste, ein TreeNode beherbergt den Name (string, Liste wird aus einer DB eingelesen) eines Form, dass bei Click aufgerufen werden soll. Da ich bisher für jeden Node ein eigenes Form hatte, welches von MyForm abgeleitet wurde. Habe ich dann anhand des String das Form geholt und es gecastet...

Der Node string sah vorher so aus: "namespace.elTorito.WindowsGUI.frmProject"

Hatte erst gedacht ich könnte einfach den String ändern in :

"namespace.elTorito.WindowsGUI.MyGenericForm<Project>"

Aber da bekam ich nur null zurück von :


Type newType = System.Type.GetType(frmName, true, true);

Also Click auf ein treeNode soll das GenerischeForm öffnen mit dem passenden Typ/Objekt (welches dem TreeNode in welcher Art und weise auch imemr hinterlegt ist)

29.05.2015 - 17:12 Uhr

Hi,

vielleicht könnt Ihr mir noch einmal helfen...

Ich hatte vor der "Genericsalisierung" ein Form so aufgerufen:


public ProjectForm :MyForm {}

string frmName = "Namespace.irgendwas.Projectform"
MyForm frm = (MyForm)(Assembly.GetExecutingAssembly().CreateInstance(frmName));
frm.Show();


Nun möchte ich anhand eines String mein Generisches Form aufrufen, aber ich verzweifle dran 😦
Wahrscheinlich ist es ganz einfach, oder mann kann es sogar wieder über ein interface lösen? 😃

Ich hatte da an soetwas in die richtung gedacht:


System.Type myType = FindType("Project");
MyGenericForm<myType>() = new MyGenericForm<myType>()  ;

Das funktioniert (natürlich) nicht ...

Hab dann auch über Interface versucht, aber irgendwie scheitere ich ständig daran dass ich T nicht "dynamisch" erzeugen kann.

Vielleicht hat noch einer eine Idee und ich hab Tomaten auf den Augen.

Danke

28.05.2015 - 15:15 Uhr

Hallo KroaX,

danke für die Antwort.

gefällt mir die Lösung mit dem Interface.
Sieht viel sauberer aus 👍

was man nicht so alles mit Interfaces anstellen kann ...

28.05.2015 - 14:37 Uhr

Hi,

ich hab ein Winform dem ich ein Typ übergebe.


public partial class MyGenericForm<T>  : Form where T: new()
{
}

MyGenericForm<Auto> mgf = new MyGenericForm<Auto>();
mgf.Show();


Ich möchte nun von diesem Form ein Event abonniern. Bevor diese Form Generisch war habe ich das wie folgt gemacht:


 var mf = this.ActiveMdiChild as MyForm;
if (mf != null)
{
    mf.bindingNavigatorAddNewItem_Click(sender, e);
}
else
{
    Form f = this.ActiveMdiChild;
}

Wie mache ich das nun mit dem Generischen Form?
Ich müsste ja erst einmal den Typ ermitteln.


System.Type constructed = this.ActiveMdiChild.GetType();

Gibt mir:
Type ist: MyGenericForm`1[Auto] zurück.

Hatte gedacht ich könnte das so machen:


if (constructed.IsGenericType)
{
    System.Type[] typeArguments = constructed.GetGenericArguments();
    var tParam = typeArguments[0];
    MyGenericForm<tParam> mfg = this.ActiveMdiChild as MyGenericForm<tParam>;
   mfg.bindingNavigatorAddNewItem_Click(sender, e);
}

Das funktioniert aber nicht.

Wie kann komme ich an den Typ und wie übergebe ich den richtig?

Danke
gruß
Peter

27.05.2015 - 18:29 Uhr

Und dabei stellte sich das Problem das die diversen Objekte jeweils nach einer anderen Spalte (eigenschaft) sortiert werden könnten

Dann ist doch das DGV für die Sortierung verantwortlich. Du meinst doch die Sortierfunktion, wenn man auf den Spaltennamen im Header klickt? Dann mußt du das doch nicht nocheinmal neu implementieren.

Jein... bin jetzt verwirrt...

das DGV soll mir immer nur dazu dienen die gebundene Liste anzuzeigen. Im DGV habe ich z.B.

Apfel
Banane
Kiwi
Mango

ich stehe auf zeile Kiwi und füge eine Zeile ein , habe nun eine Leerzeile zwischen Banane und Kiwi , ich tippe Orange ein, und die Orange soll sich in der gebunden Liste hinter Mango einfügen.

Das DGV kann ja kein ListChangedEvent, es soll immer nur abbilden was gerade darunter passiert.

das DGV kann auch nicht Sortieren durch Klick auf den Spaltennamen, wenn es an einer Liste gebunden ist.

Presenting the SortableBindingList<T>

27.05.2015 - 17:47 Uhr

Kompliziert wird die Sache bei dir, da du auf eine Trennung der Schichten verzichtest. Daher mal als Lesetip der Hinweis auf [Artikel] Drei-Schichten-Architektur.

...was aber kein Grund sein sollte, sich nicht trotzdem mal mit Generics auseinanderzusetzen. Das gehört halt einfach zu den Grundlagen, mit denen man als C#-Entwickler arbeitet.

Hi,

ja, ich versuche mich grad mit Generics auseinander zu setzen. Ich habe mich da ein bisschen verzettelt glaube ich.

Mein Ziel ist es ein Formular zu haben mit ein DGV, welches an einer Sortierbaren BindingList gebunden ist, die sortierbar sein soll, diese Liste kann mal Auto, Flugzeug, Person, Project sein...

Ich möchte dann nur das jeweilige Object angeben, und so für alle Objekte die gleichen Sortier, hinzufüge usw Funktionen benutzen. Da komme ich um Generics ja gar nicht herum.

Und dabei stellte sich das Problem das die diversen Objekte jeweils nach einer anderen Spalte (eigenschaft) sortiert werden könnten, und ich dann versuchte diese Angabe irgendwie mitzugeben, und habe mich dabei verzettelt ...

27.05.2015 - 12:25 Uhr

Hi Mr Sparkle,

hätte es wirklich soo viel Text und Code für diese eine Frage gebraucht?
wie würde man so eine Comparer Methode schreiben, damit man X Beliebige Objekte vergleichen kann?

Jein, die andere Frage war ja noch ob man es so machen könnte:

IComparer<Project> objectComparer = new CompareObject<Project>((x, y) => x.ProjectName.CompareTo(y.ProjectName));
int searchIndex = Objects.BinarySearch(item, (IComparer<object>)objectComparer);

Hab dein Link mal gelesen, aber verstehe dass nicht so wirklich, zudem bin ich noch auf den Blog hier gestoßen, wo BinarySearch erweitert wird...

Und nun zu dem Entschluss gekommen dass es wohl die falsche herangehensweise für mein Vorhaben ist. Ich Glaube, ich verkomplizier es mal wieder.

Ich hab ein DataGridView, durch drücken der Taste F3 wird eine neue Zeile eingefügt an der Stelle wo man sich gerade befindet, nach Eingabe eines Wertes, und verlassen der Zelle, soll die darunterliegende Liste sich neu sortieren und der Cursor zu der neu eingefügten Zeile wechseln.

Ich hatte BinarySearch dafür benutzt um Objekte zu vergleichen, und die tatsächliche einzufügende Position in meiner Liste zu ermitteln, und anschließend zu dieser Position zu springen. Esrt danach hatte ich neu sortiert.

Habe das nun anders gelöst, ich füge das Objekt an der Position ein wo ich gerade stehe, dann sortiere ich die Liste, hole mir die Position vom neuen Objekt und springe dahin... Ist wahrscheinlich auch weniger fehleranfällig 😃

Danke

26.05.2015 - 16:19 Uhr

Hi,

ich habe eine SortableBindingList<T> namens "Projects", wo ich die Stelle suchen möchte an der ein Objekt eingefügt werden soll:


public int BinarySearch(T item, IComparer<T> comparer)
        {
            List<T> itemsList = (List<T>)this.Items;
            return itemsList.BinarySearch(item, comparer);
        }


Project item = getProjectItem(index);

CompareProject dc = new CompareProject();
int searchIndex = Projects.BinarySearch(item, dc);
Projects.Insert(~searchIndex, item);

Ich benutze ein Comparer (hier abgeguckt)


public class CompareProject : IComparer<Project>
    {
        public int Compare(Project p1, Project p2)
        {
            int result;
            if (Project.ReferenceEquals(p1, p2))
            {
                result = 0;
            }
            else
            {
                if (p1 == null)
                {
                    result = 1;
                }
                else if (p2 == null)
                {
                    result = -1;
                }
                else
                {
                    result = StringCompare(p1.ProjectName, p2.ProjectName);
                    if (result == 0)
                    {
                         result = StringCompare(p1.ProjectName, p2.ProjectName);
                    }
                }
            }
            return result;

        }

        int StringCompare(string strFirstString, string secondString)
        {

            int result;

            if (strFirstString == null)
            {

                if (secondString == null)
                {

                    result = 0;

                }

                else
                {

                    result = 1;

                }

            }

            else
            {

                result = strFirstString.CompareTo(secondString);

            }

            return result;

        }
    }

Wie bekomme ich das Generisch, so dass ich 2 x beliebige Objekte vergleichen kann?
Spätestens nach


public class CompareObject<T> : IComparer<T>
    {
        public int Compare(T p1, T p2)
        {
...

viel mir ein das ich ja gar nicht auf p1.ProjectName zugreifen kann, ich müsste also den zu vergleichenden String schon mit übergeben?

Ich wollte mal versuchen mit:


public class CompareObject<T> : IComparer<T>
    {
        private Comparison<T> comparison;

        public CompareObject(Comparison<T> comparison)
        {
            if (comparison == null)
                throw new ArgumentNullException("comparison");
            
            this.comparison = comparison;
        }

 public int Compare(T o1, T o2)
        {
            return comparison(o1, o2);
        }

IComparer<Project> objectComparer = new CompareObject<Project>((x, y) => x.ProjectName.CompareTo(y.ProjectName));


Da aber wird gemoppert das IComparer<Project> nicht nach Icomparer<object> konvertiert werden kann.

Müsste ich dann casten?


IComparer<Project> objectComparer = new CompareObject<Project>((x, y) => x.ProjectName.CompareTo(y.ProjectName));
int searchIndex = Objects.BinarySearch(item, (IComparer<object>)objectComparer);

Kann man das so machen? Oder wie würde man so eine Comparer Methode schreiben, damit man X Beliebige Objekte vergleichen kann?

Danke

Gruß
Peter

22.05.2015 - 17:40 Uhr

Hi,

ich hab ein gebundenes Datagridview , ich gehe auf eine Zelle und ändere deren Inhalt, anschließend prüfe ich (zur Kontrolle) :


        private void MyRowLeaved(DataGridViewCellEventArgs e)
        {
            if (dataGridView1.IsCurrentRowDirty)
                Console.WriteLine("Row is Dirty");
        }

MyRowLeaved wird immer ausgeführt wenn ich die Zelle verlasse, egal ob mit Taste oder Maus Klick irgendwo hin, auch wenn ich am Rädchen drehe wird Row is Dirty ausgegeben.

Nur beim MouseWheel feuert das ListChangedEventArgs nicht , und setzt den Zelleninhalt zurück 🙁


private void Form1_MouseWheel(object sender, MouseEventArgs e)
        {
            if (e.Delta > 0) // On Scroll up mouse wheels.  
            {
                _binding.Position = _binding.Position - 3;
            }
            else  //scrolling down mouse wheels       
            {
                _binding.Position = _binding.Position + 3;
            }
        }

private async void binding_ListChanged(object sender, ListChangedEventArgs e)
{
            switch (e.ListChangedType)
            {
              ....
            }
}

Worran könnte das liegen?

Danke

gruß
Peter

[EDIT]
DGV EndEdit() vergessen 🙂 Dann klappts...


private void Form1_MouseWheel(object sender, MouseEventArgs e)
        {
datagridview.EndEdit();            
if (e.Delta > 0) // On Scroll up mouse wheels.  
            {
                _binding.Position = _binding.Position - 3;
            }
            else  //scrolling down mouse wheels       
            {
                _binding.Position = _binding.Position + 3;
            }
        }