Diskuze: C# WPF binding

C# .NET .NET (C# a Visual Basic) C# WPF binding American English version English version

Avatar
Shakul
Redaktor
Avatar
Shakul:

Ahoj! Snažím se kontrolce button nabindovat attribut Grid.Column tak, aby jsem mohl v code behind určit, kde se má kontrolka při vytvoření objevit.
XAML:

<ItemsControl ItemsSource="{Binding}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Button Content="{Binding Souradnice}" Grid.Column="{Binding Radek}" Grid.Row="{Binding Sloupec}"/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

Code behind:

public MainWindow()
{
    InitializeComponent();
    var policka = new ObservableCollection<Policko>();
    DataContext = policka;
    for (int i = 0; i < 64; i++)
    {
        policka.Add(new Policko((Souradnice)i));
    }
}

Třída políčko:

public enum Souradnice
{
    A8, B8, C8, D8, E8, F8, G8, H8,
    A7, B7, C7, D7, E7, F7, G7, H7,
    A6, B6, C6, D6, E6, F6, G6, H6,
    A5, B5, C5, D5, E5, F5, G5, H5,
    A4, B4, C4, D4, E4, F4, G4, H4,
    A3, B3, C3, D3, E3, F3, G3, H3,
    A2, B2, C2, D2, E2, F2, G2, H2,
    A1, B1, C1, D1, E1, F1, G1, H1
}
class Policko
{
    /// <summary>
    /// Vlastnost, která určuje ve výčtovém typu souřadnice
    /// </summary>
    public Souradnice Souradnice { get; private set; }
    public int Radek { get; private set; }
    public int Sloupec { get; private set; }

    public Policko(Souradnice souradnice)
    {
        Souradnice = souradnice;

        // Zjistí řádek a sloupec ze souřadnice
        Radek = (int)Math.Floor((float)Souradnice / 8);
        if (Souradnice.ToString().Contains("A"))
            Sloupec = 0;
        else if (Souradnice.ToString().Contains("B"))
            Sloupec = 1;
        else if (Souradnice.ToString().Contains("C"))
            Sloupec = 2;
        else if (Souradnice.ToString().Contains("D"))
            Sloupec = 3;
        else if (Souradnice.ToString().Contains("E"))
            Sloupec = 4;
        else if (Souradnice.ToString().Contains("F"))
            Sloupec = 5;
        else if (Souradnice.ToString().Contains("G"))
            Sloupec = 6;
        else if (Souradnice.ToString().Contains("H"))
            Sloupec = 7;
    }
}

Tlačítka se sice vytvoří, ale všechny jsou zarovnané v první buňce Gridu.
Najde se někdo, kdo by mi pověděl, čím by to mohlo být, popřípadě jak to opravit? :)

 
Odpovědět 18.11.2015 23:08
Avatar
Odpovídá na Shakul
Martin Turner:

Ahoj,

jak vypadá definice Tvého gridu?
Je v něm definován potřebný počet řádků a sloupců?

 
Nahoru Odpovědět 19.11.2015 7:32
Avatar
Shakul
Redaktor
Avatar
Odpovídá na Martin Turner
Shakul:

Jojo, tabulku mám definovanou :)

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
        <RowDefinition Height="*"/>
        <RowDefinition Height="*"/>
        <RowDefinition Height="*"/>
        <RowDefinition Height="*"/>
        <RowDefinition Height="*"/>
        <RowDefinition Height="*"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="200"/>
    </Grid.ColumnDefinitions>

    <ItemsControl ItemsSource="{Binding}">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Button Content="{Binding Souradnice}" Grid.Column="{Binding Radek}" Grid.Row="{Binding Sloupec}" BorderThickness="0"/>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</Grid>
 
Nahoru Odpovědět 19.11.2015 9:58
Avatar
Libor Šimo (libcosenior):

Všimol som si
Grid.Column="{Bin­ding Radek}" -- Column je stĺpec, nebude tam chyba? Nemám v práci VS, nemôžem to testnúť.

Nahoru Odpovědět 19.11.2015 11:00
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
patrik.valkovic
Šéfredaktor
Avatar
patrik.valkovic:

Proč tam máš ItemsControl? To vůbec nepotřebuješ, když vkládáš tlačítka do Gridu.
Vytvoř si tlačítko a zavolej na něj MojeTlacitko.Set­Value(Grid.Row­Property,Ktery­Radek);
Potom jej vlož do Gridu.
ItemsControl je panel sám o sobě.

Nahoru Odpovědět 19.11.2015 11:06
Nikdy neumíme dost na to, abychom se nemohli něco nového naučit.
Avatar
Shakul
Redaktor
Avatar
Odpovídá na Libor Šimo (libcosenior)
Shakul:

Libor Šimo (libcosenior) dobrý postřeh, už jsem si to opravil. :) Je to však jen drobná chybka, která můj problém neřeší.
patrik.valkovic ItemsControl mi umožňuje pracovat s tlačítky, kterých bude 64 (opravdu bych je nechtěl tvořit ručne, natož, kdybych chtěl změnit jeden parametr, tak bych ho musel měnit 64x) v kolekci. (ObservableCo­llection)
To zmíněné tlačítko je jen předloha, jak by mělo vypadat těch 64 tlačítek. :) V designeru nejde ani vidět. Abych vše uvedl na pravou míru, snažím se vytvořit šachovnici z tlačítek.
Těch 64 tlačítek se opravdu objeví, ale všechny jsou namrskané v prvním řádku a prvním sloupci. :)

Editováno 19.11.2015 14:49
 
Nahoru Odpovědět 19.11.2015 14:48
Avatar
Shakul
Redaktor
Avatar
Shakul:

Děkuji všem za pomoc. Řešení už jsem našel. Problém rozhodně nebyl s bindingem, protože když jsem tam dal přímo hodnotu, tak to přes to nefungovalo. Problém jsem sice nevyřešil, ale buttony jsem si vytvořil přímo v code behind a z xamlu jsem vše vymazal. Omlouvám se za svojí neznalost, ale nevěděl jsem, že lze takto jednoduše vytvářet buttony v code behind...

for (int i = 0; i < 8; i++)
{
    for (int j = 0; j < 8; j++)
    {
        Button tlacitko = new Button();
        tlacitko.SetValue(Grid.ColumnProperty, i);
        tlacitko.SetValue(Grid.RowProperty, j);
        grid.Children.Add(tlacitko);
            // Přidání do kolekce
        policka.Add(new Policko(tlacitko, (Souradnice)i));
    }
}
Editováno 19.11.2015 15:06
Akceptované řešení
+5 Zkušeností
Řešení problému
 
Nahoru Odpovědět  +1 19.11.2015 15:04
Avatar
Odpovídá na Shakul
Libor Šimo (libcosenior):

Po spustení programu sa v XAML buttony neukážu?

Nahoru Odpovědět 19.11.2015 15:32
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
patrik.valkovic
Šéfredaktor
Avatar
Odpovídá na Shakul
patrik.valkovic:

Automatická změna vzhledu se ve WPF neřeší přes ItemsControl, ani nic podobného, ale přes styly. Stylu nadefinuješ Type, ale nenadefinuješ mu Key. Potom se všem tlačítkám změní design. Eventuelně můžeš stylu nastavit Key a v cyklu přidávat pouze Style. Elegantní a krátké.
Jinak tvoje řešení : však to je přesně to, co jsem psal ;-)

Nahoru Odpovědět  +1 19.11.2015 17:22
Nikdy neumíme dost na to, abychom se nemohli něco nového naučit.
Avatar
Shakul
Redaktor
Avatar
Odpovídá na Libor Šimo (libcosenior)
Shakul:

Ukázali se, ale všechny byli zarovnané v prvním řádku a prvním sloupci... všechny tam byli natlačené :)

 
Nahoru Odpovědět 20.11.2015 9:55
Avatar
ostrozan
Redaktor
Avatar
Odpovídá na Shakul
ostrozan:

Proč Grid?
Ovšem,že jde použít, ale jako pro řazení kontrolek stejného typu za/pod sebe slouží speciální kontejner StackPanel, tak pro tvůj účel je nejvhodnější WrapPanel.

Mimochodem, ani 64 tlačítek ručně v designeru nezabere víc jak tři minuty - když víš jak na to ;-)

Takže návod na šachovnici snadno a rychle jako podle Ládi Hrušky :)

*budeme potřebovat pouze designer, myš a 5minut času

  1. přetáhneme si z toolboxu do okna WrapPanel a roztáhneme tak, aby se nám vešlo 64 Buttonů
  1. do WrapPanelu přetáhneme jeden Button - v properties, či XAMLU mu nastavíme rozměry -třeba 50x50 a vymažeme Content - to je jediné psaní v celé té srandě
  2. a teď už jedeme kopírovací bomby - vybereme button - CtrlC- a můžeme valit CtrlV, dokud nám prst neupadne, nebo nebudeme mít těch 64 Buttonů nasáčkovaných do rastru 8x8,nebo si to můžeme ulehčit a po prvních osmi zarovnat hranici WrapPanelu na poslední Button , vybrat myší těch 8 a opět kopírovat a kopírovat..... - WrapPanel, stejně jako stackPanel mají proti jiným kontejnerům tu výhodu, že kopírované prvky se řadí pěkně za/pod sebe a do řádků - jinde se skládají na sebe v levém horním rohu kontejneru
  3. na závěr nastavit width a height wrapPanelu na "auto"

*
tolik tedy Láďa Hruška - spíš jen tak pro zajímavost

a zjištění souřadnic, jakožto i další obsluha tlačítka je pak taky jednoduchou záležitotí s použitím směrovaných událostí můžeš zachytávat klik na všech 64 dítkách-tlačítkách na rodičovi-wrapPanelovi (samozřejmě i na tvém Gridu) a obsloužit je díky tomu v jedné jediné metodě

private void wrapPanel1_Prewiew_MouseLeftButtonDown(object sender,MouseButtonEventArgs e)
       {
           //pretypovani zdroje na Button
           Button butt= e.Source as Button;

           //zjisteni indexu - wrapPanel je kolekce a tak s nim muzeme pracovat
           //jako (skoro) s jakoukoli jinou kolekci
           int index=wrapPanel1.Children.IndexOf (butt);

          //zjisteni souradnic naklikleho Buttonu  (pri rastru 8x8)
           int x=0;
           int y=0;

           while(index/8>0)
           {
               x=index-=8;
               y++;
           }

          //tvuj kod
       }
 
Nahoru Odpovědět  +1 20.11.2015 20:49
Avatar
Shakul
Redaktor
Avatar
Odpovídá na ostrozan
Shakul:

Páni díky. Už jsem tak nějak dopředu přemýšlel, jak vytvořit společnou údálost ClickOnButton pro všechny tlačítka. Rozhodně využiju. :) Taky jsem nevěděl, že stack/wrap panel, pracuje se svými kontrolkami v kolekci, ale mohlo mě to napadnout...

Editováno 20.11.2015 21:58
 
Nahoru Odpovědět 20.11.2015 21:58
Avatar
ostrozan
Redaktor
Avatar
Odpovídá na Shakul
ostrozan:

Jsem rád, že ti to pomůže - no a když už jsem si s tím hrál tak jsem vyřešil i jak z toho rastru udělat šachovnici - střídání tmavých a světlých polí - tak pokud bys měl zájem.

Nechci ti ale brát radost z vymýšlení vlastních postupů a třeba to už máš vyřešené :-) .

 
Nahoru Odpovědět 20.11.2015 22:29
Avatar
Shakul
Redaktor
Avatar
Shakul:

Vyřešil jsem to svým způsobem, ale jestli ho máš elegantnější, tak se bránit nebudu. :)

public enum Souradnice
{
    A8, B8, C8, D8, E8, F8, G8, H8,
    A7, B7, C7, D7, E7, F7, G7, H7,
    A6, B6, C6, D6, E6, F6, G6, H6,
    A5, B5, C5, D5, E5, F5, G5, H5,
    A4, B4, C4, D4, E4, F4, G4, H4,
    A3, B3, C3, D3, E3, F3, G3, H3,
    A2, B2, C2, D2, E2, F2, G2, H2,
    A1, B1, C1, D1, E1, F1, G1, H1
}

        // Zjistí řádek a sloupec ze souřadnice
        Radek = (int)Math.Floor((float)Souradnice / 8);
        if (Souradnice.ToString().Contains("A"))
            Sloupec = 0;
        else if (Souradnice.ToString().Contains("B"))
            Sloupec = 1;
        else if (Souradnice.ToString().Contains("C"))
            Sloupec = 2;
        else if (Souradnice.ToString().Contains("D"))
            Sloupec = 3;
        else if (Souradnice.ToString().Contains("E"))
            Sloupec = 4;
        else if (Souradnice.ToString().Contains("F"))
            Sloupec = 5;
        else if (Souradnice.ToString().Contains("G"))
            Sloupec = 6;
        else if (Souradnice.ToString().Contains("H"))
            Sloupec = 7;

        // Obarví políčko na základě řádku a sloupce
        if (Sloupec % 2 != Radek %2)
        {
            tlacitko.Background = Brushes.Black;
        }
        else
        {
            tlacitko.Background = Brushes.White;
        }
 
Nahoru Odpovědět 20.11.2015 23:09
Avatar
Shakul
Redaktor
Avatar
Odpovídá na ostrozan
Shakul:

Zpráva nad touto patří tobě, akorát jsem tě zapomněl označit...

 
Nahoru Odpovědět 21.11.2015 1:35
Avatar
Shakul
Redaktor
Avatar
Odpovídá na ostrozan
Shakul:

Ještě jsem to trochu poupravil a ušetřil pár řádků... :)

public enum Souradnice
{
    A8, B8, C8, D8, E8, F8, G8, H8,
    A7, B7, C7, D7, E7, F7, G7, H7,
    A6, B6, C6, D6, E6, F6, G6, H6,
    A5, B5, C5, D5, E5, F5, G5, H5,
    A4, B4, C4, D4, E4, F4, G4, H4,
    A3, B3, C3, D3, E3, F3, G3, H3,
    A2, B2, C2, D2, E2, F2, G2, H2,
    A1, B1, C1, D1, E1, F1, G1, H1
}

        // Zjistí řádek a sloupec ze souřadnice
        Radek = (int)Math.Floor((float)Souradnice / 8);
        Sloupec = (int)Souradnice % 8;

        // Obarví políčko na základě řádku a sloupce
        if (Sloupec % 2 != Radek %2)
        {
            tlacitko.Background = Brushes.Black;
        }
        else
        {
            tlacitko.Background = Brushes.White;
        }
Editováno 21.11.2015 1:41
 
Nahoru Odpovědět  +1 21.11.2015 1:40
Avatar
ostrozan
Redaktor
Avatar
Odpovídá na Shakul
ostrozan:

Mám něco podobného, ale o půlku kratšího - obarvuju jen černé pole - bílé už bílé je :)

Ty si to ale nech tak , pro kombinaci jiných barev.

 
Nahoru Odpovědět  +1 21.11.2015 8:15
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 17 zpráv z 17.