Interfacing Keypad to PIC16F877A
The switch statement looks overly complicated, and at least to me wasn't immediately obvious what it was doing. I would go with a more straightforward implementation.

Like Abdullah said, delays after you set TRISD and PORTD registers may help, as well as debouncing the input.

Finally, I would get a o-scope and/or multimeter to probe on these pins to make sure everything is connected properly, toggling as expected, and make sure the keypad behaves as expected. 

EDIT:

I noticed that there are internal Schmitt Triggers on PORTD inputs that are enabled by default. This will inject some latency, though I'm not sure how much, as the datasheet doesn't say.

EDIT2 :

Added hard delays before sampling and capacitive charge removal

int getKey(void)
{
    // Like Abdullah said, these can be bytes
    // Also, you can save image space by not initializing these
    unsigned char toRet;
    unsigned char firstHalf, secHalf;

    // Clear lines (attempt to get rid of capacitive charge)
    TRISD     = 0xff; // Hop off
    PORTD     = 0x00; // Prepare to drive low
    TRISD     = 0x00; // Drive all lines
    __delay_us(10000);// Wait arbitrary about of time
    TRISD     = 0xff; // Stop driving while we change values

    // Drive first half
    PORTD     = 0xf0;
    TRISD     = 0x0f; // Hex makes things easier to read
    __delay_us(10000);
    firstHalf = (PORTD &amp; 0x0f) &gt;&gt; 0; // Mask only the stuff we care about
    TRISD     = 0xff;

    // Clear lines
    PORTD     = 0x00;
    TRISD     = 0x00;
    __delay_us(10000);
    TRISD     = 0xff;

    // Drive second half
    PORTD     = 0x0f;
    TRISD     = 0xf0;
    __delay_us(10000);
    secHalf   = (PORTD &amp; 0xf0) &gt;&gt; 4; // Mask only the stuff we care about
                                     // and shift the nibble we care about down
    TRISD     = 0xff;

    // Simple selection logic
    // Keep in mind that if multiple keys are pressed, this function will return "null"
    switch (firstHalf) {
        case 0x1:
            switch (secHalf) {
                case 0x1: toRet =   7; break; //1
                case 0x2: toRet =   8; break; //2
                case 0x4: toRet =   9; break; //3
                default:  toRet = 255; break; //null
            }
            break;
        case 0x2:
            switch (secHalf) {
                case 0x1: toRet =   4; break; //4
                case 0x2: toRet =   5; break; //5
                case 0x4: toRet =   6; break; //6
                default:  toRet = 255; break; //null
            }
            break;
        case 0x4:
            switch (secHalf) {
                case 0x1: toRet =   1; break; //7
                case 0x2: toRet =   2; break; //8
                case 0x4: toRet =   3; break; //9
                default:  toRet = 255; break; //null
            }
            break;
        case 0x8:
            switch (secHalf) {
                case 0x1: toRet =  10; break; //*
                case 0x2: toRet =   0; break; //9
                case 0x4: toRet =  11; break; //#
                default:  toRet = 255; break; //null
            }
            break;
        default:          toRet = 255; break; //null
    }
    return toRet;
}