2015-04-25 55 views
0

WPF新手在这里。我正在尝试构建一张我希望在一周中的每一天重复使用的表格。所以我把它移到了控制模板上。这里是XAML:访问C中的控件模板内的控件#

<ControlTemplate x:Key="defaultGridDesign" > 
      <Grid HorizontalAlignment="Center" Margin="0,5"> 
       <Grid.ColumnDefinitions> 
        <ColumnDefinition Width="80"/> 
        <ColumnDefinition Width="80"/> 
        <ColumnDefinition Width="200"/> 
        <ColumnDefinition Width="60"/> 
        <ColumnDefinition Width="60"/> 
        <ColumnDefinition Width="60"/> 
        <ColumnDefinition Width="60"/> 
        <ColumnDefinition Width="60"/> 
        <ColumnDefinition Width="60"/> 
        <ColumnDefinition Width="60"/> 
        <ColumnDefinition Width="60"/> 
        <ColumnDefinition Width="200"/> 
        <ColumnDefinition Width="200"/> 
       </Grid.ColumnDefinitions> 
       <Grid.RowDefinitions> 
        <RowDefinition Height="30"/> 
        <RowDefinition Height="60"/> 
        <RowDefinition Height="60"/> 
       </Grid.RowDefinitions> 

       <Label x:Name="lblDayOfWeek" Style="{StaticResource BasicLabelLeft}" Grid.Row="0" Grid.Column="0" Grid.RowSpan="3" Content="Monday"/> 
       <Label x:Name="lblEmpty" Style="{StaticResource BasicLabelLeft}" Grid.Row="0" Grid.Column="1"/> 
       <Label x:Name="lblPlanned" Style="{StaticResource BasicLabelLeft}" Content="Planned" Grid.Row="1" Grid.Column="1"/> 
       <Label x:Name="lblProduced" Style="{StaticResource BasicLabelLeft}" Content="Produced" Grid.Row="2" Grid.Column="1"/> 
       <Label x:Name="lblPrevShift" Style="{StaticResource BasicLabelCenter}" Content="Previous Shift" Grid.Row="0" Grid.Column="2" /> 
       <Label x:Name="lblPlannedPrevShift" Style="{StaticResource BasicLabelLeft}" Content="n/a" Grid.Row="1" Grid.Column="2" /> 
       <Label x:Name="lblProducedPrevShift" Style="{StaticResource BasicLabelLeft}" Content="n/a" Grid.Row="2" Grid.Column="2" /> 
       <Label x:Name="lbl1stHr" Style="{StaticResource BasicLabelCenter}" Content="01" Grid.Row="0" Grid.Column="3" /> 
       <Label x:Name="lbl2ndHr" Style="{StaticResource BasicLabelCenter}" Content="02" Grid.Row="0" Grid.Column="4" /> 
       <Label x:Name="lbl3rdHr" Style="{StaticResource BasicLabelCenter}" Content="03" Grid.Row="0" Grid.Column="5" /> 
       <Label x:Name="lbl4thHr" Style="{StaticResource BasicLabelCenter}" Content="04" Grid.Row="0" Grid.Column="6" /> 
       <Label x:Name="lbl5thHr" Style="{StaticResource BasicLabelCenter}" Content="05" Grid.Row="0" Grid.Column="7" /> 
       <Label x:Name="lbl6thHr" Style="{StaticResource BasicLabelCenter}" Content="06" Grid.Row="0" Grid.Column="8" /> 
       <Label x:Name="lbl7thHr" Style="{StaticResource BasicLabelCenter}" Content="07" Grid.Row="0" Grid.Column="9" /> 
       <Label x:Name="lbl8thHr" Style="{StaticResource BasicLabelCenter}" Content="08" Grid.Row="0" Grid.Column="10"/> 
       <Label x:Name="lblTotal" Style="{StaticResource BasicLabelCenter}" Content="Total" Grid.Row="0" Grid.Column="11"/> 
       <Label x:Name="lblNextShift" Style="{StaticResource BasicLabelCenter}" Content="Next Shift" Grid.Row="0" Grid.Column="12"/> 
       <Label x:Name="lblPlannedTotal" Style="{StaticResource BasicLabelLeft}" Content="n/a" Grid.Row="1" Grid.Column="11"/> 
       <Label x:Name="lblPlannedNextShift" Style="{StaticResource BasicLabelLeft}" Content="n/a" Grid.Row="1" Grid.Column="12"/> 
       <Label x:Name="lblProducedTotal" Style="{StaticResource BasicLabelLeft}" Content="n/a" Grid.Row="2" Grid.Column="11"/> 
       <Label x:Name="lblShiftOEE" Style="{StaticResource BasicLabelLeft}" Content="n/a" Grid.Row="2" Grid.Column="12"/> 
       <StackPanel x:Name="stkPnlPlanned" Grid.Row="1" Grid.Column="3" Grid.ColumnSpan="8" Width="480"/> 
       <StackPanel x:Name="stkPnlProduced" Grid.Row="2" Grid.Column="3" Grid.ColumnSpan="8" Width="480"/> 
      </Grid> 
     </ControlTemplate> 

这是我如何实例化它们:

<StackPanel> 
     <ContentControl Template="{StaticResource defaultGridDesign}" x:Name="ccTuesday"></ContentControl> 
     <ContentControl Template="{StaticResource defaultGridDesign}" x:Name="ccWednesday" /> 
     <ContentControl Template="{StaticResource defaultGridDesign}" x:Name="ccThursday" /> 
     <ContentControl Template="{StaticResource defaultGridDesign}" x:Name="ccFriday" /> 
     <ContentControl Template="{StaticResource defaultGridDesign}" x:Name="ccSaturday" /> 
     <ContentControl Template="{StaticResource defaultGridDesign}" x:Name="ccMonday" /> 
    </StackPanel> 

现在,我撞了南墙,是当我想要绑定的控件模板内的标签。我在网上找到的每一个绑定例子都使用了一个基本的例子,我还没有找到一个能够解决这种情况的例子。我基本上想在第一列设置小时数,第一列设置小时数,但最终我需要根据从Excel文件中读取的内容来填充堆叠面板。我期望堆叠面板的装订/填充是一个完整的其他球场。每个表获得不同的信息。每个小时,我需要更新它们中的每一个。

我已经试过这无济于事:

Label test = (Label) this.ccTuesday.Template.FindName("lblDayOfWeek", ccTuesday); 

但结果是零。

而且我一直在这里看着这个讨论: https://codereview.stackexchange.com/questions/44760/is-there-a-better-way-to-get-a-child

但它确实似乎为了访问一个标签,一个很大的开销。

同样,我是一个新手,所以我不知道我是否正确地做了。也许有更好更优雅的方式来做到这一点。欢迎任何建议。

编辑1:
以下作品的答案,但是当我尝试执行视图和模型之间的ViewModel类,在这个环节http://www.codeproject.com/Articles/819294/WPF-MVVM-step-by-step-Basics-to-Advance-Level#Level3:-Addingactionsand“INotifyPropertyChanged的”接口

标签回去空着。

View类:

public partial class MainWindow : Window 
    { 
     private TableViewModel tableViewModelMonday = null; 
     private TableViewModel tableViewModelTuesday = null; 

     public MainWindow() 
     { 
      InitializeComponent(); 
      try 
      { 
       this.tableViewModelMonday = new TableViewModel("Monday"); 
       this.tableViewModelTuesday = new TableViewModel("Tuesday"); 
      } 
      catch (Exception ex) 
      { 
       MessageBox.Show(ex.Message); 
      } 
     } 

     private void ccTuesday_Loaded(object sender, RoutedEventArgs e) 
     { 
      this.ccTuesday.DataContext = this.tableViewModelTuesday; 
     } 

     private void ccMonday_Loaded(object sender, RoutedEventArgs e) 
     { 
      this.ccMonday.DataContext = this.tableViewModelMonday; 
     } 

的App.xaml中,其中结合是:

<Label x:Name="lblDayOfWeek" Style="{StaticResource BasicLabelLeft}" Grid.Row="0" Grid.Column="0" Grid.RowSpan="3" Content="{Binding dayOfWeek}"/> 

视图模型类:

public class TableViewModel : INotifyPropertyChanged 
    { 
     private TableModel tableModel = null; 

     public TableViewModel(string day) 
     { 
      tableModel = new TableModel(day); 
     } 

     public string lblDayOfWeek 
     { 
      get 
      { 
       return tableModel.dayOfWeek; 
      } 
      set 
      { 
       if (tableModel.dayOfWeek != value) 
       { 
        tableModel.dayOfWeek = value; 
        this.OnNotifyPropertyChanged("dayOfWeek"); 
       } 
      } 
     } 

     private void OnNotifyPropertyChanged(string msg) 
     { 
      if (this.PropertyChanged != null) 
      { 
       this.PropertyChanged(this, new PropertyChangedEventArgs(msg)); 
      } 
     } 

     public event PropertyChangedEventHandler PropertyChanged; 

    } 

和模型类:

public class TableModel 
    { 
     private string _dayOfWeek; 

     public string dayOfWeek 
     { 
      get 
      { 
       return this._dayOfWeek; 
      } 
      set 
      { 
       if (this._dayOfWeek != value) 
       { 
        this._dayOfWeek = value; 
       } 
      } 
     } 

     public TableModel(string day) 
     { 
      this._dayOfWeek = day; 
     } 
    } 

我错过了什么?

+0

你能指定你想通过'Template.FindName(“lblDayOfWeek”,ccTuesday)获得标签吗?在构造函数或其他地方? – Grx70

+0

@ Grx70在主窗口的构造函数中,只是为了测试出来 – CostaRica

+0

好吧,那就是问题 - 在这一点上,控件被实例化,但是它们的模板还没有被应用,因此'null'结果。一旦应用了模板,您就需要使用这种方法 - 您最好的办法是在'Window'或'ContentControl'本身上订阅'Loaded'事件。或者,如果您需要在加载控件之前获取模板内容,请创建一个来自“ContentControl”(甚至是“Control”,如果您不打算放入任何内容)的控件,并覆盖“ OnApplyTemplate'方法。 – Grx70

回答

1

您也可以通过UserControl实现该可重用性。无论哪种方式,为了获得绑定功能,您可以定义一个Model类型并将其分配给ContentControl(或UserControl)的DataContext属性。

首先,绑定的ContentTemplate内侧的标签:

<Label x:Name="lblDayOfWeek" 
     Style="{StaticResource BasicLabelLeft}" 
     Grid.Row="0" 
     Grid.Column="0" 
     Grid.RowSpan="3" 
     Content="{Binding DayOfWeek}"/> 

然后定义模型类:

public class Model : INotifyPropertyChanged { 
    private DayOfWeek dayOfWeek; 
    public DayOfWeek DayOfWeek { 
     get { 
      return this.dayOfWeek; 
     } 
     set { 
      if (this.dayOfWeek != value) { 
       this.dayOfWeek = value; 
       this.OnNotifyPropertyChanged("DayOfWeek"); 
      } 
     } 
    } 
    private void OnNotifyPropertyChanged(string name) { 
     if (this.PropertyChanged != null) { 
      this.PropertyChanged(this, new PropertyChangedEventArgs(name)); 
     } 
    } 
    public event PropertyChangedEventHandler PropertyChanged; 
} 

然后,你需要创建模型的实例,并将其分配到DataContext:

public partial class MainWindow : Window { 
    private ModelClass model = new ModelClass(); 
    public MainWindow() { 
     InitializeComponent(); 
     this.customUserControl.DataContext = this.model; 
    } 

    private void button_Click(object sender, RoutedEventArgs e) { 
     this.model.DayOfWeek = DayOfWeek.Sunday; 
    } 
} 

现在,无论何时更改模型对象的DayOfWeek属性,绑定标签在ContentTemplate中得到更新。

关于动态添加项目到StackPanel,你可以考虑使用ItemsControl类。

为了让您知道,MVVM模式是用于设计WPF应用程序的最常见设计模式。遵循这种模式,您可以使用强大的WPF功能,如绑定更好。

+0

感谢您的回答。有用。但是当我在视图和模型之间放置一个ViewModel类时,标签会回到null。 INotifyPropertyChanged是在ViewModel类中实现的,它仅包含模型,仅此而已。在View类中,我根据上面的注释触发加载事件后设置dataContext。任何想法是怎么回事?让我知道你是否需要看代码。我正在阅读此链接(http://www.codeproject.com/Articles/819294/WPF-MVVM-step-by-step-Basics-to-Advance-Level#Level3:-Addingactionsand“INotifyPropertyChanged”interface) – CostaRica

+0

你确定Label的绑定路径仍然是指一个有效的属性吗?考虑他上面的例子,你的视图模型是否暴露了DayOfWeek属性?是的,如果我看到我可以帮助更好的代码。 –

相关问题