Vítejte na blog.vyvojar.cz Přihlásit | Registrovat | Pomoc

Pro usnadnění práce s Gridem mě napadlo takové vylepšení jak si ulehčit práci s definování jednotlivých řádků. Místo definice v XAMLu, jsem si vytvořil vlastní Grid, který má vlastnost RowDefinitionPattern, kterou lze nastavit jednoduše na hodnotu např.": RowDefinitionPattern="50 50 150 20 1 A" (mezera slouží jako oddělovač a hodnoty jsou v celku intuitivní)

image

Dalším usnadněním, které mě v této souvislosti napadlo bylo automatické generování řádku dle toho v jakém pořadí jsou UIElementy v Gridu:

Občas se mi stává, že mám Grid rozdělený na 20 řádků a zrovna poslední řádek potřebuju vložit na první místo. Tzn. přepsat všechny vlastnosti Grid.Row což je velice otravné, obzvlášť když testujete několik variant rozložení jednotlivých prvků. Řešením může být přepsání metody OnInitialized, kde projdeme všechny UIElementy v kolekci Children a inkrementálně nastavíme Grid.Row. UIElementy budou mít tedy číslo řádku právě takové, v jakém pořadí se nacházejí v XAMLu.

image

Posted 12. ledna 2012 12:22 by lukaashek | 1 Comments
Vedeno pod:

Určitě se Vám někdy stalo, že jste chtěli použít Binding na statickou vlastnost a ono to jednoduše nešlo. Nyní je vše jinak a velice jednoduše můžete nabindovat cokoli z UI na statickou vlastnost.

Notifikace změny statické vlastnosti se může provádět dvěma způsoby:

  1. pomocí static event EventHandler <název-vlastnosti>Changed – pokud máme ovšem více statických vlastností, musíme mít více handlerů.
  2. nebo pomocí static event EventHandler<PropertyChangedEventArgs> StaticPropertyChanged – kde jednoduše předáme pouze název vlastnosti

Další změnou je i syntaxe Bindingu, která využívá klasické závorky: Text="{Binding Path=(local:Class1.Abc)}"

Xaml i code-behind je pro oba případy stejný

image

image

Add 1.

image

Add 2.

image

Posted 12. ledna 2012 10:55 by lukaashek | 0 Comments
Vedeno pod:

Třída BindingBase se rozrostla o novou vlastnost Delay. Tato vlastnost nám umožní specifikovat čas (v ms) než dojde k aktualizaci zdroje. Ukázkové použití:

Máme formulář, kde jsou jednotlivé vlastnosti nabindované na TextBox, respektivě na jejich vlastnost Text. Jakmile uživatel píše do TextBoxu, hodnota se díky módu TwoWay propisuje automaticky do naši vlastnosti, kde provádíme nějakou akci (např. validace, apod.) Někdy je ovšem nepodstatné aby se tato kontrola prováděla při každém stisku klávesy a v tom případě můžeme nastavit Delay na pár sekund, které by teoreticky mohly stačit k vyplnění příslušné hodnoty a binding po uplynutí této doby aktualizuje zdroj a validace se provede 1x.

Poznámka: Pokud chcete používat Delay, musí být hodnota Mode=TwoWay a UpdateSourceTrigger=PropertyChanged

image

image

Ukázka z aplikace:

image

Po uplynutí 3s:

image

Závěr:

Při testování zadání hodnoty s mezerou např.": “sdf sdfs sdf sdfs sdf” to přestane ovšem fungovat a VS zahlásí chybu:

System.Windows.Data Error: 8 : Cannot save value from target back to source. BindingExpression:Path=Name; DataItem='DelayDataBinding' (Name='aaa'); target element is 'TextBox' (Name=''); target property is 'Text' (type 'String') ArgumentException:'System.ArgumentException: 'sdf sdfs sdf sdfs sdf' is not a valid value for property 'Name'.
   at System.Windows.DependencyObject.SetValueCommon(DependencyProperty dp, Object value, PropertyMetadata metadata, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType, Boolean isInternal)
   at System.Windows.DependencyObject.SetValue(DependencyProperty dp, Object value)
   at MS.Internal.Data.PropertyPathWorker.SetValue(Object item, Object value)
   at MS.Internal.Data.ClrBindingWorker.UpdateValue(Object value)
   at System.Windows.Data.BindingExpression.UpdateSource(Object value)'

Vypadá to asi na nějaké bug.

Moje chyba, používal jsem název vlastnosti Name, který už ovšem existuje v rámci UserControlu.

Posted 10. ledna 2012 13:30 by lukaashek | 4 Comments
Vedeno pod:

WPF 4.5 nabízí novou metodu, která nám umožní přistupovat ke kolekci z různých vláken. V UI vlákně kolekci vytvoříme, ve vlákně na pozadí jí modifikujeme a data se nám zobrazí bez žádného problému v UI. Metoda EnableCollectionSynchronization přebírá jako parametr pouze kolekci a objekt k synchronizovanému přístupu ke kolekci:

image

Posted 10. ledna 2012 12:48 by lukaashek | 1 Comments
Vedeno pod:

V dnešním článku si ukážeme jak napsat vlastní “WatermarkedTextBox”. Jedná se o klasický TextBox, který je rozšířen o vodoznak (doplňující informace co se zde má např. vyplnit).

Začínáme

Ve VS vytvoříme nový projekt typu “WPF Custom Control Library” (Standardně se vytvoří i nová třída CustomControl.cs, kterou můžeme smazat) a pojmenujeme ho jako “CustomControls”. Pro začátek stačí když si vytvoříme hlavní třídu “WatermarkedTextBox”

[TemplatePart(Name = "PART_TextBox", Type = typeof(TextBox))]
[TemplatePart(Name = "PART_TextBlock", Type = typeof(TextBlock))]
public class WatermarkedTextBox : TextBox
{
    static WatermarkedTextBox()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(WatermarkedTextBox),
            new FrameworkPropertyMetadata(typeof(WatermarkedTextBox)));
    }
}

WatermarkedTextBox se bude skládat z klasického TextBoxu (pojmenovaný jako PART_TextBox) a TextBlocku (PART_TextBlock) sloužící pro zobrazení vodoznaku. Pomocí metody OverrideMetada, kterou voláme v konstruktoru řekneme, že chceme využít styl definovaný v souboru Generic.xaml

<Style TargetType="local:WatermarkedTextBox">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="local:WatermarkedTextBox">
                <Grid>
                    <TextBox x:Name="PART_TextBox"/>
                    <TextBlock x:Name="PART_TextBlock"/>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Aby jsme si mohli tento hrubý základ otestovat, vytvoříme novou WPF aplikaci, přidáme referenci na knihovnu CustomControls a vložíme WatermarkedTextBox do hlavního okna MainWindow

<Window xmlns:my="clr-namespace:CustomControls;assembly=CustomControls" 
        x:Class="CustomControls.Demo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <my:WatermarkedTextBox  Height="50" Margin="10"/>
    </Grid>
</Window>

Po spuštění aplikace se nám zobrazí náš control, ale žádný vodoznak není vidět a navíc nejde do něho ani psát. Pojďme tedy přidat základní funkcionalitu.

Základní funkcionalita

Pro vytvoření základní funkcionality budeme potřebovat následující vlastnosti:

  • Watermark – text, který se zobrazí jako vodoznak
  • WatermarkForeground – barva vodoznaku
  • WatermarkStyle – styl vodoznaku
public static readonly DependencyProperty WatermarkProperty = DependencyProperty.Register(
    "Watermark",
    typeof(string),
    typeof(WatermarkedTextBox),
    new PropertyMetadata("Zadejte text..."));
public static readonly DependencyProperty WatermarkStyleProperty = DependencyProperty.Register(
    "WatermarkStyle",
    typeof(Style),
    typeof(WatermarkedTextBox));
public static readonly DependencyProperty WatermarkForegroundProperty = DependencyProperty.Register(
    "WatermarkForeground",
    typeof(Brush),
    typeof(WatermarkedTextBox),
    new PropertyMetadata(new SolidColorBrush(Color.FromArgb(255, 134, 134, 134))));
[Description("Vrati nebo nastavi vodoznak")]
public string Watermark
{
    get { return (string)GetValue(WatermarkProperty); }
    set { SetValue(WatermarkProperty, value); }
}
[Description("Vrati nebo nastavi styl vodoznaku")]
public Style WatermarkStyle
{
    get { return (Style)GetValue(WatermarkStyleProperty); }
    set { SetValue(WatermarkStyleProperty, value); }
}
[Description("Vrati nebo nastavi barvu vodoznaku")]
public Brush WatermarkForeground
{
    get { return (Brush)GetValue(WatermarkForegroundProperty); }
    set { SetValue(WatermarkForegroundProperty, value); }
}

Všechny potřebné vlastnosti jsou definovány jako jednoduché Dependency property a není potřeba provádět v kódu na pozadí nějaké další věci. O vše ostatní se postaráme přímo v XAMLu.

Nejdříve rozšíříme TextBlock, který se bude starat o zobrazení vodoznaku:

 <TextBlock x:Name="PART_TextBlock"
            Style="{TemplateBinding WatermarkStyle}"
            Foreground="{TemplateBinding WatermarkForeground}"
            Text="{TemplateBinding Watermark}"/>

Nyní umí náš TextBlock zobrazit defaultní vodoznak (můžete si to vyzkoušet spuštěním aplikace). Problém je stále v tom, že do TextBoxu nelze psát. Tento problém vyřešíme nastavením vlastnosti IsHitTestVisible na false u elementu TextBlock.

Další problém nám spočívá vtom, že když začneme psát do TextBoxu, vodoznak nezmizí, ale je stále vidět což nepůsobí dobře. U tohoto řešení využijeme triggery, kterými definujeme chování vodoznaku:

  • Pokud je hodnota Textu - null zobraz vodoznak
  • Pokud je hodnota Textu prázdný řetězec – zobraz vodoznak
  • Pokud je hodnota Textu nějaký řetězec – schovej vodoznak
<ControlTemplate.Triggers>
    <DataTrigger Binding="{Binding Path=Text, ElementName=PART_TextBox}" Value="{x:Null}">
        <Setter TargetName="PART_TextBlock" Property="Visibility" Value="Visible"/>
    </DataTrigger>
    <DataTrigger Binding="{Binding Path=Text.Length, ElementName=PART_TextBox}" Value="0">
        <Setter TargetName="PART_TextBlock" Property="Visibility" Value="Visible"/>
    </DataTrigger>
</ControlTemplate.Triggers>

Na závěr ještě upravíme chování tabelátoru nastavením vlastnosti IsTabStop celému WatermarkedTextBoxu na False a vnitřímu TextBoxu na true.

na závěr ještě kompletní souhrn:

WatermarkedTextBox:

namespace CustomControls
{
    using System.Windows.Media;
    using System.Windows;
    using System.Windows.Controls;
    using System.ComponentModel;
    [TemplatePart(Name = "PART_TextBox", Type = typeof(TextBox))]
    [TemplatePart(Name = "PART_TextBlock", Type = typeof(TextBlock))]
    public class WatermarkedTextBox : TextBox
    {
        public static readonly DependencyProperty WatermarkProperty = DependencyProperty.Register(
                "Watermark",
                typeof(string),
                typeof(WatermarkedTextBox),
                new PropertyMetadata("Zadejte text..."));
        public static readonly DependencyProperty WatermarkStyleProperty = DependencyProperty.Register(
            "WatermarkStyle",
            typeof(Style),
            typeof(WatermarkedTextBox));
        public static readonly DependencyProperty WatermarkForegroundProperty = DependencyProperty.Register(
            "WatermarkForeground",
            typeof(Brush),
            typeof(WatermarkedTextBox),
            new PropertyMetadata(new SolidColorBrush(Color.FromArgb(255, 134, 134, 134))));
        static WatermarkedTextBox()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(WatermarkedTextBox),
                new FrameworkPropertyMetadata(typeof(WatermarkedTextBox)));
        }
        [Description("Vrati nebo nastavi vodoznak")]
        public string Watermark
        {
            get { return (string)GetValue(WatermarkProperty); }
            set { SetValue(WatermarkProperty, value); }
        }
        [Description("Vrati nebo nastavi styl vodoznaku")]
        public Style WatermarkStyle
        {
            get { return (Style)GetValue(WatermarkStyleProperty); }
            set { SetValue(WatermarkStyleProperty, value); }
        }
        [Description("Vrati nebo nastavi barvu vodoznaku")]
        public Brush WatermarkForeground
        {
            get { return (Brush)GetValue(WatermarkForegroundProperty); }
            set { SetValue(WatermarkForegroundProperty, value); }
        }
    }
}

Generic.xaml:

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:CustomControls">
  
    <Style TargetType="local:WatermarkedTextBox">
        <Setter Property="IsTabStop" Value="False"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="local:WatermarkedTextBox">
                    <Grid>
                        <TextBox x:Name="PART_TextBox" IsTabStop="True"/>
                        <TextBlock x:Name="PART_TextBlock"
                                   Style="{TemplateBinding WatermarkStyle}"
                                   Foreground="{TemplateBinding WatermarkForeground}"
                                   Text="{TemplateBinding Watermark}"
                                   IsHitTestVisible="False"
                                   Visibility="Hidden"/>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <DataTrigger Binding="{Binding Path=Text, ElementName=PART_TextBox}" Value="{x:Null}">
                            <Setter TargetName="PART_TextBlock" Property="Visibility" Value="Visible"/>
                        </DataTrigger>
                        <DataTrigger Binding="{Binding Path=Text.Length, ElementName=PART_TextBox}" Value="0">
                            <Setter TargetName="PART_TextBlock" Property="Visibility" Value="Visible"/>
                        </DataTrigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    
</ResourceDictionary>

MainWindow.xaml:

<Window xmlns:my="clr-namespace:CustomControls;assembly=CustomControls" 
        x:Class="CustomControls.Demo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.Resources>
            <Style x:Key="watermarkStyle" TargetType="{x:Type my:WatermarkedTextBox}">
                <Setter Property="WatermarkForeground" Value="#FF868686" />
                <Setter Property="WatermarkStyle">
                    <Setter.Value>
                        <Style TargetType="TextBlock">
                            <Setter Property="HorizontalAlignment" Value="Left" />
                            <Setter Property="Margin" Value="10,0,0,0" />
                            <Setter Property="VerticalAlignment" Value="Center" />
                            <Setter Property="FontStyle" Value="Italic" />
                            <Setter Property="TextWrapping" Value="NoWrap" />
                        </Style>
                    </Setter.Value>
                </Setter>
            </Style>
        </Grid.Resources>
        <my:WatermarkedTextBox x:Name="wtxt1"  Height="50" Margin="10"/>
        <my:WatermarkedTextBox x:Name="wtxt2"  Height="50" Margin="8,186,12,75"
                               Watermark="Vyplnte pozadovane udaje"
                               Style="{StaticResource watermarkStyle}"/>
    </Grid>
</Window>

Implementace vlastního WatermarkedTextBoxu byla vcelku jednoduchá a výsledný projekt si můžete stáhnout na adrese https://skydrive.live.com/redir.aspx?cid=35f7223b2eb524fd&resid=35F7223B2EB524FD!314&parid=35F7223B2EB524FD!313

Lukáš

Markup Extensions umožňují rozšířit funkcionalitu XAMLu. WPF již obsahuje vestavěné Markup Extensions jako je např. NullExtension, StaticExtension, Binding apod. Tyto rozšíření poznáte jednoduše, vyskytují se v xamlu mezi složenými závorkami. Např.

Obr. Markup Extensions (Windows Presentation Foundation Unleashed)

image

Vytvoření vlastního rozšíření je velice jednoduché, stačí pouze podědit ze třídy MarkupExtension (namespace System.Windows.Markup) a implementovat metodu ProvideValue, která se postará o vrácení správné hodnoty. Pro ukázku možného použití se podíváme na následující jednoduché ukázky.

StringToBoolExtension – převádí řetězec ano na true či false

namespace BoolMarkupExtension
{
    using System;
    using System.Windows.Markup;
    /// <summary>
    ///Implementace vlastniho MarkupExtension. Retezec prevede na bool objekt
    /// </summary>
    [MarkupExtensionReturnType(typeof(bool))]
    public class StringToBoolExtension : MarkupExtension
    {
        public string Value { get; set; }
        /// <summary>
        /// Vraci objekt, ktery se nastavi jako hodnota atributu na nehoz je toto rozsireni aplikovano
        /// </summary>
        /// <param name="serviceProvider"></param>
        /// <returns></returns>
        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            bool isEnabled = false;
            if (string.Equals("ano", Value, StringComparison.OrdinalIgnoreCase))
                isEnabled = true;
            return isEnabled;
        }
    }
}

Použití v XAMLu:

<Window x:Class="BoolMarkupExtension.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:ex="clr-namespace:BoolMarkupExtension"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel>
        <Button IsEnabled="{ex:StringToBool Value=ano}" Content="StringToBool" />      
    </StackPanel>
</Window>

Poznámka: Název třídy by měl mít suffix Extension. Není to povinné, spíše se jedná o doporučení. I když např. třída Binding tento suffix nemá! Při použití v XAMLu lze ovšem tento suffix ignorovat a použít pouze název třídy bez suffixu např. Static – i když se třída jmenuje StaticExtension

CurrentTimeExtension – umožní zobrazit aktuální čas

namespace BoolMarkupExtension
{
    using System.Windows.Markup;
    using System.Windows;
    using System.Windows.Threading;
    using System;
    [MarkupExtensionReturnType(typeof(string))]
    public class CurrentTimeExtension : MarkupExtension
    {
        DispatcherTimer _timer;
        UIElement _uiElement;
        DependencyProperty _dependencyProperty;
        /// <summary>
        /// Vytvori instanci tridy <see cref="CurrentTimeExtension"/>
        /// </summary>
        public CurrentTimeExtension()
        {
            _timer = new DispatcherTimer(TimeSpan.FromSeconds(1),
                                         DispatcherPriority.Background,
                                         (sender, args) =>
                                             {
                                                 _uiElement.SetValue(_dependencyProperty,DateTime.Now.ToLongTimeString());
                                             }, Dispatcher.CurrentDispatcher);
        }
        public override object ProvideValue(System.IServiceProvider serviceProvider)
        {
            IProvideValueTarget target = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget));
            _uiElement = (UIElement)target.TargetObject;
            _dependencyProperty = (DependencyProperty)target.TargetProperty;
            return DateTime.Now.ToLongTimeString();
        }
    }
}

Použití v XAMLu:

<Window x:Class="BoolMarkupExtension.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:ex="clr-namespace:BoolMarkupExtension"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel>
        <TextBlock Text="{ex:CurrentTime}"/>
    </StackPanel>
</Window>

BoolToVisibilityExtension – na základě bool hodnoty vrátí hodnotu z enumu Visibility – Visible/Hidden. Toto rozšíření je vhodné v situaci, že máme nabindovaný nějaký ViewModel na View. Do vlastnosti Path nastavím název property ve ViewModelu, která může nabývat hodnot true/false. V metodě ProvideValue jsem pak schopný z DataContextu získat tento ViewModel a vytvořit Binding mezi cílovou vlastností (Path) a DependencyProperty, která bude hodnotu zobrazovat (v našem případě Button). Využívá se zde již existující konvertor BooleanToVisibilityConverter. Pokud hodnota vlastnosti ve ViewModelu bude true, tlačítko bude zobrazené, jinak bude schované.

namespace BoolMarkupExtension
{
    using System.Windows.Controls;
    using System.Windows.Markup;
    using System.Windows;
    using System.Windows.Data;
    [MarkupExtensionReturnType(typeof(Visibility))]
    public class BoolToVisibilityExtension : MarkupExtension
    {
        private object _dataContext;
        private FrameworkElement _uiElement;
        public string Path { get; set; }
        public override object ProvideValue(System.IServiceProvider serviceProvider)
        {
            IProvideValueTarget target = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget));
            _uiElement = target.TargetObject as FrameworkElement;
            _dataContext = _uiElement.DataContext;
            var dp = target.TargetProperty as DependencyProperty;
            
            Binding binding = new Binding();
            binding.Path = new PropertyPath(Path);
            binding.Source = _dataContext;
            binding.Mode = BindingMode.TwoWay;
            binding.Converter = new BooleanToVisibilityConverter(); // built-in konverter
            _uiElement.SetBinding(dp, binding);
            return _uiElement.GetValue(dp);
        }
    }
}

Použití v XAMLu:

<Window x:Class="BoolMarkupExtension.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:ex="clr-namespace:BoolMarkupExtension"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel>
        <CheckBox x:Name="chb" IsChecked="{Binding Visible, Mode=TwoWay}"/>
        <Button Visibility="{ex:BoolToVisibility Path=Visible}" Content="test"/>
    </StackPanel>
</Window>

Závěr

I když dělám z WPF již nějakou dobu, byla pro mě tvorba vlastních Markup Extension docela novinkou. Třeba to bude něco nového i pro některé z Vás. Ukázkové solution si můžete stáhnout na http://lukaskubis.net/demos/BoolMarkupExtensionSample.zip

01 - Copy

02 - Copy

03 - Copy

04 - Copy

05 - Copy

06 - Copy

07 - Copy

08 - Copy

09 - Copy

10 - Copy

11 - Copy

12 - Copy

13 - Copy

14

15

16

17

18

19

----------------------------------

Lukáš Kubis
školení, konzultace, zakázkový vývoj
http://web.lukaskubis.net

Posted 3. srpna 2011 20:23 by lukaashek | 2 Comments
Vedeno pod:

01

02

03

04

05

----------------------------------

Lukáš Kubis
školení, konzultace, zakázkový vývoj
http://web.lukaskubis.net

image

image

image

image

  • Create a new IIS web site - Sharepoint – 80
  • Port – 80
  • Host Header –
  • Path - C:\inetpub\wwwroot\wss\VirtualDirectories\80
  • Authentication Provider – NTLM
  • Allow Anonymous – No
  • Use Secure Sockets Layer (SSL) – No
  • Url – http://TFS2010DC:80
  • Zone – Default
  • Create new application pool – Sharepoint – 80
    • Select a security account for this application pool – Predefined (Network Service)
  • Restart IIS Manually
  • Database Server – TFS2010DC
  • Database Name – WSS_Content
  • Database Authentication – Windows Authentication (recommended)
  • OK

image

----------------------------------

Lukáš Kubis
školení, konzultace, zakázkový vývoj
http://web.lukaskubis.net

01 - Copy

02 - Copy

03 - Copy

04

05 - Copy

06

07

08 - Copy

09 - Copy

10 - Copy

11

12

13

14 - Copy

----------------------------------

Lukáš Kubis
školení, konzultace, zakázkový vývoj
http://web.lukaskubis.net

RS01

RS02

RS03 - Copy

RS04 - Copy

RS05 - Copy

RS05A - Copy

RS05B

RS05C

RS05D - Copy

RS05E

RS05F

RS06 - Copy

RS07 - Copy

RS08

RS09

----------------------------------

Lukáš Kubis
školení, konzultace, zakázkový vývoj
http://web.lukaskubis.net

Instalace TFS 2010 vyžaduje SQL Server 2008. Máme ovšem na výběr ze tří možností:

  1. Pro konfiguraci „basic“ lze využít i SQL Server 2008 v Express edici
  2. Nainstalovat SQL Server 2008
  3. Použít existující instalaci SQL Serveru 2008

Podporované edice

  • SQL Server 2008 – Express, Standard, Enterprise
  • SQL Server 2008 R2 – Express, Standard, Enterprise

Servisní účet

  • Doménový nebo vestavěný účet

Instalace krok za krokem

SQL01 - Copy

SQL02 - Copy

SQL03

SQL04 - Copy

 

SQL05

SQL06

SQL07

SQL08 - Copy

SQL09 - Copy

SQL10

SQL11 - Copy

SQL12

SQL13 - Copy

SQL14 - Copy

SQL15 - Copy

SQL16 - Copy

SQL17

SQL18

SQL19

SQL20

----------------------------------

Lukáš Kubis
školení, konzultace, zakázkový vývoj
http://web.lukaskubis.net

Informace níže vycházejí ze souboru Installation Guide for Team Foundation, kde je detailně rozepsáno vše potřebné pro instalaci a konfiguraci Team Foundation Serveru 2010 (dále jen TFS).

Operační systémy

TFS ve verzi 2010 lze nainstalovat kromě serverové části i na klientský počítač. Pro instalaci na server je potřeba, aby byl nainstalován jeden z následujících operačních systémů:

  • 32-bit verze Windows Serveru 2003 (Datacenter, Enterprise nebo Standard edice) se SP2
  • 32-bit verze Windows Serveru 2003 R2 (Datacenter, Enterprise nebo Standard edice)
  • 32-bit verze Windows Serveru 2003 R2 (Datacenter, Enterprise nebo Standard edice) se SP2
  • Windows Server 2008 1 se SP2
  • Windows Server 2008 1 R2
  • Windows Server 2008 1 R2 SP1

Pro instalaci na klientský počítač musí být nainstalován jeden z následujících operačních systémů:

  • Windows Vista (Home Premisum, Business, Enterprise nebo Ultimate edice) se SP2
  • Windows 7 (Home Premium, Professional, Enterprise nebo Ultimate edice)
  • Windows 7 se SP1 (Home Premium SP1, Professional SP1, Enterprise SP1 nebo Ultimate SP1 edice)

1 TFS nepodporuje instalaci typu „Server Core“.

Podpora pro 64-bit instalaci

TFS 64-bit nelze nainstalovat na Windows Server 2003, nýbrž pouze na Windows Server 2008.

Účty potřebné k instalaci

Reportovací účet

Slouží pro sběr informací pro reporty. Tento účet je při defaultní instalaci TFS rovněž použit jako servisní účet pro Windows Sharepoint Services.

  • Reporting (TFSREPORTS)
    • Musí mít oprávnění „Allow log on locally“
    • Defaultní účet: neexistuje, je potřeba specifikovat konkrétní účet

Servisní účty

Servisní účty slouží pro spouštění windows služeb následujících komponent:

  • Team Foundation Server (TFSSERVICE – ukázkový účet)
    • Musí mít oprávnění „Log on as a service“
    • Pokud instalujeme TFS pod účtem domain\user1, nelze tento účet použít jako účet pro TFSSERVICE
    • Defaultní účet: Network Service
  • Team Foundation Build (TFSBUILD)
    • Musí mít oprávnění „Log on as a service“
    • Defaultní účet: Network Service
  • Team Foundation Server Proxy (TFSPROXY)
    • Musí mít oprávnění „Log on as a service“
    • Defaultní účet: Network Service

Servisní účty pro ostatní software

  • Sharepoint (WSSERVICE)
    • Potřeba uvést konkrétní účet
    • Při defaultní instalaci TFS je použit stejný účet jako pro reportovací účet
  • SQL Server (SQLSERVICE)
    • Potřeba vytvořit účet před instalací TFS

----------------------------------

Lukáš Kubis
školení, konzultace, zakázkový vývoj
http://web.lukaskubis.net

Včera jsem objevil další zajímavou funkci a to NTILE(int). Tato funkce se používá pro rozdělení dat do přibližně stejných skupin. Např. budu-li chtít rozdělit tabulku produktů do 6-ti přibližně stejných skupin, použiju NTILE(6).

Kromě jednoduché rozdělení můžeme využít NTILE i v nějaké vlastní proceduře, která pro nás bude provádět např. stránkování na straně serveru:

USE AdventureWorksLT2008

DECLARE @pageSize    INT
DECLARE @pageIndex    INT
DECLARE @count        INT

SELECT @count = COUNT(*) FROM SalesLT.Customer
SET @pageSize = 10;
SET @pageIndex = 1;

-- NTILE(int)
WITH Pages AS
(SELECT c.CustomerID, c.FirstName, c.LastName, c.SalesPerson
    , NTILE(@count / @pageSize) OVER(ORDER BY c.CustomerID ASC) AS PageIndex
FROM SalesLT.Customer c)
SELECT a.CustomerID, a.FirstName, a.LastName, a.SalesPerson
FROM SalesLT.Customer a INNER JOIN Pages b ON a.CustomerID = b.CustomerID
    WHERE b.PageIndex = @pageIndex;
GO

V mém případě mám definované proměnné pageSize (velikost stránky), pageIndex (aktuální stránka) a count (celkový počet řádků). Jako parametr pro funkci NTILE pak použiju výsledek po dělení celkového počtu řádků a velikost jedné stránky (count / pageSize). Nakonec jenom přidám podmínku WHERE, kde upřesním jakou stránku chci vrátit.

----------------------------------

Lukáš Kubis
školení, konzultace, zakázkový vývoj
http://web.lukaskubis.net

Zrovna jsem objevil pro mě zajimavou informaci ohledně cizích klíčů. Vezměme v potaz dvě tabulky Customers a Orders:

CREATE TABLE Customers (
    CustomerID    INT    PRIMARY KEY
)

CREATE TABLE Orders (
    OrderID    INT    PRIMARY KEY
    , CustomerID    INT    NOT NULL
        CONSTRAINT FKOrdersCustomers
            REFERENCES Customers(CustomerID)
)

Budeme-li chtít provést následující dotaz:

SELECT o.* FROM Orders AS o
WHERE EXISTS(SELECT * FROM Customers AS c
            WHERE c.CustomerID = o.CustomerID);

tak na “Estimated plánu” můžeme vidět, že se do tabulky Customers vůbec nepřistupuje. Optimalizátor totiž ví, že je nastavený cizí klíč což zaručuje, že každá objednávka musí mít vazbu na zákazníka a tudíž není potřeba vůbec do tabulky Customers přistupovat.

image

Provedeme-li úpravu tabulky Order a zrušíme-li cizí klíč

ALTER TABLE Orders NOCHECK CONSTRAINT FKOrdersCustomers

tak po provedení stejného dotazu bude “estimated plán” jiný. Není totiž jisté, že každá ojednávka bude mít nějakého zákazníka.

image

Pokud opět nastavíme kontrolu cizíko klíče

ALTER TABLE Orders CHECK CONSTRAINT FKOrdersCustomers

Tak nám “estimated plán” vrátí stejný výsledek! SQL Server si totiž nemůže být jistý, zda se náhodou v tabulce Orders nevyskytují špatné vazby na zákazníky. Informaci, zda SQL Server považuje cizí klíč za důvěryhodný si můžeme ověřit pomocí jednoduchého selectu

SELECT name, is_not_trusted FROM sys.foreign_keys
WHERE name = 'FKOrdersCustomers'

Pokud je hodnota is_not_trusted = 1, považuje SQL Server tento klíč za nedůvěryhodný. Změnu z nedůvěryhodného na důvěryhodny lze provést rovněž jednoduchým selectem a to za použítí klíčového slova WITH CHECK

ALTER TABLE Orders
    WITH CHECK
    CHECK CONSTRAINT FKOrdersCustomers

Nyní po spuštění “Estimated plánu” uvidíme stejný výsledek jako je uveden na prvním obrázku.

Toť vše.

----------------------------------

Lukáš Kubis
školení, konzultace, zakázkový vývoj
http://web.lukaskubis.net

Více článků Další stránka »
 
Vyvojar.cz na prodej!