2010-03-12 68 views
4

我開始了一個WPF項目,剛剛完成了UI的基礎,但它看起來非常複雜,所以我不確定我是否已經以正確的方式進行了佈局。我不想開始開發後端,並意識到我已經犯了錯誤,讓自己的生活變得更加艱難。我的代碼是否表現出很好的WPF實踐?

來自<的背景DIV>的樣式和CSS的風格有很大的不同,真的很想從頭開始。

本質上講,它是一個星期的日曆(7天,週一至週日,默認爲當前周)。這將最終連接到一個數據庫,如果我有一個預約在這一天的東西,它會顯示它在相關日子。

我選擇了網格而不是ListView,因爲它的工作方式我不會將結果綁定到集合或沿着這些行的任何東西。相反,我會在畫布上爲每個事件填充一個組合框(尚未放置在代碼中),並在選擇時向我顯示更多細節。

XAML:

 
<Window x:Class="WOW_Widget.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:s="clr-namespace:System;assembly=mscorlib" 
    xmlns:Extensions="clr-namespace:WOW_Widget" 
    DataContext="{Binding RelativeSource={RelativeSource Self}}" 
    Title="Window1" Height="239" Width="831"> 

    <Window.Resources> 
     <LinearGradientBrush x:Key="NormalBrush" StartPoint="0,0" EndPoint="0,1"> 
      <GradientBrush.GradientStops> 
       <GradientStopCollection> 
        <GradientStop Offset="1.0" Color="White"/> 
        <GradientStop Offset="0.0" Color="LightSlateGray"/> 
       </GradientStopCollection> 
      </GradientBrush.GradientStops> 
     </LinearGradientBrush> 
     <LinearGradientBrush x:Key="grdDayHeader" StartPoint="0,0" EndPoint="0,1"> 
      <GradientBrush.GradientStops> 
       <GradientStopCollection> 
        <GradientStop Offset="0.0" Color="Peru" /> 
        <GradientStop Offset="1.0" Color="White" /> 
       </GradientStopCollection> 
      </GradientBrush.GradientStops> 
     </LinearGradientBrush> 
     <LinearGradientBrush x:Key="grdToday" StartPoint="0,0" EndPoint="0,1"> 
      <GradientBrush.GradientStops> 
       <GradientStopCollection> 
        <GradientStop Offset="0.0" Color="LimeGreen"/> 
        <GradientStop Offset="1.0" Color="DarkGreen" /> 
       </GradientStopCollection> 
      </GradientBrush.GradientStops> 
     </LinearGradientBrush> 
     <Style TargetType="{x:Type GridViewColumnHeader}"> 
      <Setter Property="Background" Value="Khaki" /> 
     </Style> 
     <Style x:Key="DayHeader" TargetType="{x:Type Label}"> 
      <Setter Property="Background" Value="{StaticResource grdDayHeader}" /> 
      <Setter Property="Width" Value="111" /> 
      <Setter Property="Height" Value="25" /> 
      <Setter Property="HorizontalContentAlignment" Value="Center" /> 
     </Style> 
     <Style x:Key="DayField"> 
      <Setter Property="Canvas.Width" Value="111" /> 
      <Setter Property="Canvas.Height" Value="60" /> 
      <Setter Property="Canvas.Background" Value="White" /> 
     </Style> 
     <Style x:Key="Today"> 
      <Setter Property="Canvas.Background" Value="{StaticResource grdToday}" /> 
     </Style> 
     <Style x:Key="CalendarColSpacer"> 
      <Setter Property="Canvas.Width" Value="1" /> 
      <Setter Property="Canvas.Background" Value="Black" /> 
     </Style> 
     <Style x:Key="CalendarRowSpacer"> 
      <Setter Property="Canvas.Height" Value="1" /> 
      <Setter Property="Canvas.Background" Value="Black" /> 
     </Style> 
    </Window.Resources> 

    <Grid Background="{StaticResource NormalBrush}"> 
     <Border BorderBrush="Black" BorderThickness="1" Width="785" Height="86" Margin="12,12,12,104"> 
      <Canvas Height="86" Width="785" VerticalAlignment="Top"> 
       <Grid> 
        <Grid.ColumnDefinitions> 
         <ColumnDefinition /> 
         <ColumnDefinition /> 
         <ColumnDefinition /> 
         <ColumnDefinition /> 
         <ColumnDefinition /> 
         <ColumnDefinition /> 
         <ColumnDefinition /> 
         <ColumnDefinition /> 
         <ColumnDefinition /> 
         <ColumnDefinition /> 
         <ColumnDefinition /> 
         <ColumnDefinition /> 
         <ColumnDefinition /> 
        </Grid.ColumnDefinitions> 
        <Grid.RowDefinitions> 
         <RowDefinition /> 
         <RowDefinition /> 
         <RowDefinition /> 
        </Grid.RowDefinitions> 
        <Label Grid.Column="0" Grid.Row="0" Content="Monday" Style="{StaticResource DayHeader}" /> 
        <Canvas Grid.Column="1" Grid.RowSpan="3" Grid.Row="0" Style="{StaticResource CalendarColSpacer}" /> 
        <Label Grid.Column="2" Grid.Row="0" Content="Tuesday" Style="{StaticResource DayHeader}" /> 
        <Canvas Grid.Column="3" Grid.RowSpan="3" Grid.Row="0" Style="{StaticResource CalendarColSpacer}" /> 
        <Label Grid.Column="4" Grid.Row="0" Content="Wednesday" Style="{StaticResource DayHeader}" /> 
        <Canvas Grid.Column="5" Grid.RowSpan="3" Grid.Row="0" Style="{StaticResource CalendarColSpacer}" /> 
        <Label Grid.Column="6" Grid.Row="0" Content="Thursday" Style="{StaticResource DayHeader}" /> 
        <Canvas Grid.Column="7" Grid.RowSpan="3" Grid.Row="0" Style="{StaticResource CalendarColSpacer}" /> 
        <Label Grid.Column="8" Grid.Row="0" Content="Friday" Style="{StaticResource DayHeader}" /> 
        <Canvas Grid.Column="9" Grid.RowSpan="3" Grid.Row="0" Style="{StaticResource CalendarColSpacer}" /> 
        <Label Grid.Column="10" Grid.Row="0" Content="Saturday" Style="{StaticResource DayHeader}" /> 
        <Canvas Grid.Column="11" Grid.RowSpan="3" Grid.Row="0" Style="{StaticResource CalendarColSpacer}" /> 
        <Label Grid.Column="12" Grid.Row="0" Content="Sunday" Style="{StaticResource DayHeader}" /> 

        <Canvas Grid.Column="0" Grid.ColumnSpan="13" Grid.Row="1" Style="{StaticResource CalendarRowSpacer}" /> 

        <Canvas Grid.Column="0" Grid.Row="2" Margin="0" Style="{StaticResource DayField}"> 
         <Label Name="lblMondayDate" /> 
        </Canvas> 
        <Canvas Grid.Column="2" Grid.Row="2" Margin="0" Style="{StaticResource DayField}"> 
         <Label Name="lblTuesdayDate" /> 
        </Canvas> 
        <Canvas Grid.Column="4" Grid.Row="2" Margin="0" Style="{StaticResource DayField}"> 
         <Label Name="lblWednesdayDate" /> 
        </Canvas> 
        <Canvas Grid.Column="6" Grid.Row="2" Margin="0" Style="{StaticResource DayField}"> 
         <Label Name="lblThursdayDate" /> 
        </Canvas> 
        <Canvas Grid.Column="8" Grid.Row="2" Margin="0" Style="{StaticResource DayField}"> 
         <Label Name="lblFridayDate" /> 
        </Canvas> 
        <Canvas Grid.Column="10" Grid.Row="2" Margin="0" Style="{StaticResource DayField}"> 
         <Label Name="lblSaturdayDate" /> 
        </Canvas> 
        <Canvas Grid.Column="12" Grid.Row="2" Margin="0" Style="{StaticResource DayField}"> 
         <Label Name="lblSundayDate" /> 
        </Canvas> 
       </Grid> 
      </Canvas> 
     </Border> 
     <Canvas Height="86" HorizontalAlignment="Right" Margin="0,0,12,12" Name="canvas1" VerticalAlignment="Bottom" Width="198"></Canvas>   
    </Grid> 
</Window> 

CS:

public partial class Window1 : Window { 
    private DateTime today = new DateTime(); 
    private Label[] Dates = new Label[7]; 
    public Window1() { 
     DateTime start = today = DateTime.Now; 
     int day = (int)today.DayOfWeek; 
     while (day != 1) { 
      start = start.Subtract(new TimeSpan(1, 0, 0, 0)); 
      day--; 
     } 
     InitializeComponent(); 
     Dates[0] = lblMondayDate; 
     Dates[1] = lblTuesdayDate; 
     Dates[2] = lblWednesdayDate; 
     Dates[3] = lblThursdayDate; 
     Dates[4] = lblFridayDate; 
     Dates[5] = lblSaturdayDate; 
     Dates[6] = lblSundayDate; 
     FillWeek(start); 
    } 

    private void FillWeek(DateTime start) { 
     for (int d = 0; d &lt; Dates.Length; d++) { 
      TimeSpan td = new TimeSpan(d, 0, 0, 0); 
      DateTime _day = start.Add(td); 
      if (_day.Date == today.Date) { 
       Canvas dayCanvas = (Canvas)Dates[d].Parent; 
       dayCanvas.Style = (Style)this.Resources["Today"]; 
      } 
      Dates[d].Content = (int)start.Add(td).Day; 
     } 
    } 
} 
+3

除非你有一個特定的錯誤信息或部分卡住,否則我會說這種類型的問題會更適合[代碼評論](https://codereview.stackexchange.com/)現場。 – 2017-06-06 16:57:59

回答

11

我會說,不,你不會這樣做的正確方法。你做了太多的工作,並讓WPF做得太少。你應該使用數據綁定和ItemsControl,並讓WPF做所有重要工作,弄清楚在哪裏放置東西以及放入什麼東西。

  1. 我在這個例子中使用的XmlDataProvider因爲它演示瞭如何數據綁定能夠無需編寫代碼中使用的最簡單的方法。您可能會構建一個視圖模型類,該類使用Name和Date屬性公開了一組對象並綁定到該對象的一個​​實例。

  2. 使用Canvas和逐像素佈局是WPF中的一件壞事,這完全是關於構建與分辨率無關的UI。讓佈局引擎完成所有工作要好得多。

  3. 並非所有看起來像網格的東西都需要與Grid一起佈置。如果將此網格放置爲水平方向,則XAML要少得多。這樣可以避免使用行號和列號。我的佈局使用Grid的唯一原因是將邊框大小設置爲其內容。

這是我對你提供的返工。在我看來,結果與您的結果看起來非常相似,但它大約是XAML的一半(不包括筆刷),修改起來更容易。

<Page 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Background="{DynamicResource NormalBrush}"> 

    <Page.Resources> 
     <XmlDataProvider x:Key="Days" XPath="Days"> 
     <x:XData> 
      <Days xmlns=""> 
      <Day Name="Sunday" Date="03/14/2010"/> 
      <Day Name="Monday" Date="03/15/2010"/> 
      <Day Name="Tuesday" Date="03/16/2010"/> 
      <Day Name="Wednesday" Date="03/17/2010"/> 
      <Day Name="Thursday" Date="03/18/2010"/> 
      <Day Name="Friday" Date="03/19/2010"/> 
      <Day Name="Saturday" Date="03/20/2010"/> 
      </Days> 
     </x:XData> 
     </XmlDataProvider> 

     <LinearGradientBrush x:Key="NormalBrush" StartPoint="0,0" EndPoint="0,1"> 
      <GradientBrush.GradientStops> 
       <GradientStopCollection> 
        <GradientStop Offset="1.0" Color="White"/> 
        <GradientStop Offset="0.0" Color="LightSlateGray"/> 
       </GradientStopCollection> 
      </GradientBrush.GradientStops> 
     </LinearGradientBrush> 

     <LinearGradientBrush x:Key="DayHeaderBrush" StartPoint="0,0" EndPoint="0,1"> 
      <GradientBrush.GradientStops> 
       <GradientStopCollection> 
        <GradientStop Offset="0.0" Color="Peru" /> 
        <GradientStop Offset="1.0" Color="White" /> 
       </GradientStopCollection> 
      </GradientBrush.GradientStops> 
     </LinearGradientBrush>   

    </Page.Resources> 
     <Grid Margin="50"> 
      <Grid.RowDefinitions> 
      <RowDefinition Height="Auto"/>    
      </Grid.RowDefinitions> 
      <Grid.ColumnDefinitions> 
      <ColumnDefinition Width="Auto"/> 
      </Grid.ColumnDefinitions> 
      <StackPanel Orientation="Horizontal"> 
      <ItemsControl ItemsSource="{Binding Source={StaticResource Days}, XPath=Day}"> 
       <ItemsControl.ItemsPanel> 
       <ItemsPanelTemplate> 
        <StackPanel Orientation="Horizontal"/> 
       </ItemsPanelTemplate> 
       </ItemsControl.ItemsPanel> 
       <ItemsControl.ItemTemplate> 
       <DataTemplate> 
       <StackPanel Orientation="Vertical" Background="White"> 
        <Border BorderBrush="Black" BorderThickness="1,1,0,0" Background="{StaticResource DayHeaderBrush}"> 
         <TextBlock Margin="30,10" HorizontalAlignment="Center" Text="{Binding [email protected]}"/> 
        </Border> 
        <Border BorderBrush="Black" BorderThickness="1,1,0,0"> 
         <TextBlock Margin="30,10" Height="50" HorizontalAlignment="Center" Text="{Binding [email protected]}"/> 
        </Border> 
        </StackPanel> 
       </DataTemplate> 
       </ItemsControl.ItemTemplate> 
      </ItemsControl> 
      <Border BorderBrush="Black" BorderThickness="0,0,1,0"/> 
      </StackPanel> 
     </Grid> 
</Page> 
+0

我想補充一點,您可能還想考慮創建一個適當的自定義控件(將其放置在資源字典中的樣式中):https:// www .tutorialspoint.com/wpf/wpf_custom_controls.htm大約一半。 – sondergard 2016-10-05 18:20:57

3

我不知道你的項目是如何大的將是,但最大的尖端開始WPF是看的時候,我可以給你進入PRISM框架:

http://www.codeplex.com/CompositeWPF

http://msdn.microsoft.com/en-us/magazine/cc785479.aspx

這是一個很好的框架,爲您解決了很多問題。

關於你的日曆,我會建議使其成爲一個可重複使用的查找控制較少,這篇文章可以幫助你:

http://www.codeproject.com/KB/WPF/WPFOutlookCalendar.aspx

+1

對於未來的讀者和WPF初學者,我強烈建議不要從PRISM開始,然後才能理解WPF基礎知識。而且,「優秀的框架」是一種主觀的。我會說這是一個「低於標準的框架」,可以解決一些問題,但創造了許多其他問題。 – UrbanEsc 2017-10-11 12:11:58

+0

我可以給出的最大提示是避免任何類似PRISM的框架 – sam 2018-02-09 14:49:17