1
votes

I'm relatively new to WPF and so there are some Problems.

I need UserControls and I have a trouble with one which contains a ComboBox. I need to set the Value within Initialisation, but it doesn't work. And I need the ChangedEvent routed to the MainWindow.

My UserControl-XAML:

<UserControl x:Class="xyz.FileLineDropBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
Name="UC">
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="30" />
        <ColumnDefinition Width="110" />
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="30" />
    </Grid.ColumnDefinitions>

    <Label Grid.Column="1" VerticalAlignment="Center" Content="{Binding ElementName=UC, Path=Description}" />
    <ComboBox Grid.Column="2" VerticalAlignment="Center" HorizontalAlignment="Left" Width="40" SelectionChanged="valueChangedEventHandler" SelectedItem="Value">
        <!-- simple Alternative to Spin / NumericUpDown -->
        <ComboBoxItem Content="1" />
        <ComboBoxItem Content="2" />
        <ComboBoxItem IsSelected="True" Content="3" />
        <ComboBoxItem Content="4" />
    </ComboBox>
</Grid>

My UserControl-Behind-Code:

namespace xyz{
public partial class FileLineDropBox : UserControl {
    ...
    //Description///////////////////////////////////////////////////////////
    public string Description{
        get { return (string)GetValue(DescriptionProperty); }
        set { SetValue(DescriptionProperty, value); }
    }

    public static readonly DependencyProperty DescriptionProperty = DependencyProperty.Register("Description", typeof(string), typeof(FileLineDropBox), new UIPropertyMetadata(""));

    //Value/////////////////////////////////////////////////////////////////
    public string Value{
        get { return (string)GetValue(ValueProperty); }
        set { SetValue(ValueProperty, value); }
    }

    public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(string), typeof(FileLineDropBox), new UIPropertyMetadata(""));

    ////////////////////////////////////////////////////////////////////////
    // Eventhandler (Text / Selection changed)
    private void valueChangedEventHandler(object sender, SelectionChangedEventArgs e){
        SelectionChangedEventArgs args = new SelectionChangedEventArgs(ValueChangedEvent, e.RemovedItems, e.AddedItems);
        RaiseEvent(args);
    }

    ////////////////////////////////////////////////////////////////////////
    // Routing the EventHandler up to the MainWindow
    public static readonly RoutedEvent ValueChangedEvent = EventManager.RegisterRoutedEvent("ValueChangedEvent", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(FileLineDropBox));
    public event SelectionChangedEventHandler ValueChanged{
        add { AddHandler(ValueChangedEvent, value); }
        remove { RemoveHandler(ValueChangedEvent, value); }
    }
}

In MainWindow-Behind-Code I want to set the Value, but it is not linked to the wanted Value (Selection). And the Adding of the EventHandler causes an Error while Executing:

    public partial class MainWindow : Window {
    FileLineDropBox     myLineDropBox;

    public MainWindow() {
        ...
        Init3_CodedComponents();
        myLineDropBox.Value                     = "4";
    }

    private void Init3_CodedComponents(){
        AddHandler(FileLineDropBox.ValueChangedEvent, new SelectionChangedEventHandler(FileLineComboBox_CntChangedEvent));  // Abo of EventHandler from FileLine
        ...
        myLineDropBox                           = new FileLineDropBox();
        myLineDropBox.Description               = "blub";
        myGrids[1].Children.Add(myLineDropBox);
        myGrids[1].RowDefinitions.Add(new RowDefinition());
        Grid.SetRow(myLineDropBox, linePos);
        ...
    }

    ...

    private void FileLineComboBox_CntChangedEvent(object sender, SelectionChangedEventArgs e){
        if(!isInitialized)return;
        ComboBox myCb = sender as ComboBox;
        int maxId;
        string sMaxId = (e.AddedItems[0] as ComboBoxItem).Content as string;
        int.TryParse(sMaxId, out maxId);
        ...
    }
}

Edit, Solution for first Problem is following:

  1. changed in XAML:

    <ComboBox Grid.Column="2" ... Name="FileLineCB" ... />

  2. removed Value-Binding-Code from Behind Code

  3. added in Behind-Code:

    public void CB_Add_Item(string NewItem) {
        this.FileLineCB.Items.Add(NewItem);
    }
    
    public void CB_Select_Item(string SelectThis) {
        this.FileLineCB.SelectedItem = SelectThis;
    }
    
1
Ok, first thing is solved. To set the Items and the SelectedIndex I chooses a very simple Solution. The ComboBox now has a Name and the Class has two Functions to set the wished Things. 1. changed in XAML: <ComboBox Grid.Column="2" ... Name="FileLineCB" ... /> 2. removed Value-Binding-Code from Behind Code 3. added in Behind-Code: public void CB_Add_Item(string NewItem) { this.FileLineCB.Items.Add(NewItem); } public void CB_Select_Item(string SelectThis) { this.FileLineCB.SelectedItem = SelectThis; }Nobse
sorry - above is not readable. Again: First thing is solved. But I still have the Problem with my EventHandler. Anybody could tell me pls where my Mistake is?Nobse

1 Answers

0
votes

Problems solved, but maybe not the best Way. If one has a better or more recommended Way, pls add this here.

Here is my Solution: XAML

<UserControl x:Class="xyz.FileLineDropBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
Name="UC">
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="30" />
        <ColumnDefinition Width="110" />
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="30" />
    </Grid.ColumnDefinitions>

    <Label Grid.Column="1" VerticalAlignment="Center" Content="{Binding ElementName=UC, Path=Description}" />
    <ComboBox Grid.Column="2" VerticalAlignment="Center" HorizontalAlignment="Left" Width="40" Name="FileLineCB" SelectedItem="{Binding ElementName=UC, Path=Value}" SelectionChanged="valueChangedEventHandler" />
</Grid>

Behind-Code:

namespace xyz {
public partial class FileLineDropBox : UserControl {
    ...
    //Changing ComboBox/////////////////////////////////////////////////////
    public void CB_Add_Item(string NewItem) {
        this.FileLineCB.Items.Add(NewItem);
    }

    public void CB_Select_Item(string SelectThis) {
        this.FileLineCB.SelectedItem = SelectThis;
    }

    //Value/////////////////////////////////////////////////////////////////
    public string Value{
        get { return (string)GetValue(ValueProperty); }
        set { SetValue(ValueProperty, value); }
    }

    public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(string), typeof(FileLineDropBox), new UIPropertyMetadata(""));

    ////////////////////////////////////////////////////////////////////////
    // Eventhandler (Text / Selection changed)
    private void valueChangedEventHandler(object sender, RoutedEventArgs e){
        RaiseEvent(new RoutedEventArgs(FileLineDropBox.ValueChangedEvent));
    }

    ////////////////////////////////////////////////////////////////////////
    // Routing the EventHandler up to the MainWindow
    public static readonly RoutedEvent ValueChangedEvent = EventManager.RegisterRoutedEvent("ValueChangedEvent", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(FileLineDropBox));
    public event RoutedEventHandler ValueChanged{
        add { AddHandler(ValueChangedEvent, value); }
        remove { RemoveHandler(ValueChangedEvent, value); }
    }
}

}

MainWindow:

    //init
    private void Init3_CodedComponents(){
        myLineDropBox.CB_Add_Item("1");
        myLineDropBox.CB_Add_Item("2");
        ...
        myLineDropBox.CB_Select_Item("4");
        ...
        AddHandler(FileLineDropBox.ValueChangedEvent, new RoutedEventHandler(FileLineComboBox_CntChangedEvent));
    }

    // EventHandler
    private void FileLineComboBox_CntChangedEvent(object sender, RoutedEventArgs e){
        ...
        int.TryParse(myLineDropBox.Value, out maxId);
        ...
    }